2016-11-29 41 views
0

(例如得到std::list<some_value_type>std::list在C++ 11中是否有从指定模板参数的模板类获取通用模板类?

考虑下面的代码:

#include <list> 
#include <string> 

std::string combine(int val, std::string str) 
{ 
    return std::to_string(val) + str; 
} 

template <class T, class U> 
auto foo(const T &container, const U &val) 
    -> std::list<U> 
{ 
    using RetType = std::list<U>; 
    RetType result; 

    for(auto item : container) { 
     result.push_back(combine(item, val)); 
    } 

    return result; 
} 

int main() 
{ 
    std::list<int> numbers = {1, 2, 3, 4, 5}; 
    std::list<std::string> result = foo(numbers, std::string(" potato")); 
    return 0; 
} 

这编译,但我想它的工作方式不同。我希望foo能够返回与第一个参数相同类型的容器,但其值类型已更改为第二个参数的值类型,即U

因此,如果foo作为其第一个参数传入std::list<int>,而std::string作为其第二个参数,则返回std::list<std::string>。或者,如果foostd::vector<int>作为其第一个参数并且std::string作为其第二个参数传递,则返回std:: vector<std::string>。等等。

基本上我想将std::list<U>的两个实例都替换成完成上述操作的东西,可能使用<type_traits>的工具。

有没有办法在C++ 11中做到这一点?我找到的唯一解决方案是为我想要使用的每种容器类型创建foo的重载版本,但我更希望如果有一种通用的方法来实现它,它涵盖所有容器类型。

回答

4

是的,你可以使用一个模板,模板参数list<T>每次出现更改为通用C<T>

template <template<class...>class C, class T, class U> 
auto 
foo(const C<T> &container, const U &val) -> C<U> 
{ 
    using RetType = C<T>; 
    // ... 
} 

这是常用的另一种方法是使用迭代这是一个通用的接口转换成一个容器的元素。可使用的标准算法是std::transform

transform(numbers.begin(), numbers.end(), inserter(result, result.begin()), [] (int n) { 
    return combine(n, " potato"); 
}); 
+0

这并不支持自定义的分配(或hashers /比较器等,为'set' /'unordered_set') –

+0

我不知道,你可以使用省略号当指定一个模板模板类时。谢谢! – GuyGizmo

+0

@ T.C。你是对的,但为了我的目的,这已经够好了。如果我确实需要使用自定义分配器,比较器或hashers,我可以使用像'template auto foo(const C &container,const U&val) - > C '。这将需要分配器/比较器可以采取任何一种类型,但我认为它可以工作。 – GuyGizmo

相关问题