【问题标题】:In C++11 is there anyway to get the general template class from a template class with specified template arguments?在 C++11 中是否有从具有指定模板参数的模板类中获取通用模板类?
【发布时间】:2016-11-29 17:36:11
【问题描述】:

(例如,从 std::list<some_value_type> 获取 std::list

考虑以下代码:

#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&lt;int&gt;std::string 作为第二个参数传入,则返回std::list&lt;std::string&gt;。或者,如果将foo 作为第一个参数传入std::vector&lt;int&gt;,将std::string 作为第二个参数传入,则返回std:: vector&lt;std::string&gt;。以此类推。

基本上我想用可以完成上述操作的东西替换std::list&lt;U&gt; 的两个实例,可能使用&lt;type_traits&gt; 的设施。

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

【问题讨论】:

    标签: c++ c++11 templates typetraits


    【解决方案1】:

    是的,您可以使用 模板模板参数并将每次出现的 list&lt;T&gt; 更改为通用 C&lt;T&gt;

    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");
    });
    

    【讨论】:

    • 这不支持自定义分配器(或set/unordered_set 的哈希器/比较器等)
    • 我不知道在指定模板模板类时可以使用省略号。谢谢!
    • @T.C.你是对的,但就我的目的而言,这已经足够了。如果我确实需要使用自定义分配器、比较器或哈希器,我可以使用 template&lt;class C, class T, class U, class V, class W&gt; auto foo(const C&lt;T, V, W&gt; &amp;container, const U &amp;val) -&gt; C&lt;U, V, W&gt; 之类的东西重载 foo。它需要可以采用任何一种类型的分配器/比较器,但我认为它可以工作。
    • @GuyGizmo“分配器......可以采用任何一种类型”不存在;你必须重新绑定它们。
    • @T.C.你是对的。我现在更深入地研究分配器,我意识到我所说的都是无稽之谈。
    猜你喜欢
    • 2018-06-25
    • 2012-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多