【问题标题】:Can I return a templated container of different type?我可以返回不同类型的模板容器吗?
【发布时间】:2014-02-14 15:09:59
【问题描述】:

我怎样才能创建一个这样的函数?我似乎无法正确声明返回类型。

template <typename C, typename T0, typename T1>
typename C<T1> 
convert_container(const C<T0>& container, T1 value) {
  C<T1> new_container;
  // Do some stuff...
  return new_container;
}

std::vector<int> vec0;
const auto& vec1 = convert_container(vec0, float(2.0f)); // Produce a vector of floats

std::list<int> lst0;
const auto& lst1 = convert_container(lst0, float(2.0f)); // Produce a list of floats

【问题讨论】:

标签: c++ templates generic-programming template-templates


【解决方案1】:

正确的方法是使用模板模板参数:

  • C++11:

    template <template<typename...> class C, typename T0, typename T1>
    C<T1> convert_container(const C<T0>& container, T1 value) {
      C<T1> new_container;
      // Do some stuff...
      return new_container;
    }
    
  • C++03(带有分配器重新绑定):

    template <template<typename, typename> class C, typename T0, typename T1, typename Alloc>
    C<T1, typename Alloc::template rebind<T1>::other>
    convert_container(const C<T0, Alloc>& container, T1 value) {
      C<T1, typename Alloc::template rebind<T1>::other> new_container;
      // Do some stuff...
      return new_container;
    }
    
  • C++03(不重新绑定):

    template <template<typename, typename> class C, typename T0, typename T1, typename Alloc>
    C<T1, std::allocator<T1> > convert_container(const C<T0, Alloc>& container, T1 value) {
      C<T1, std::allocator<T1> > new_container;
      // Do some stuff...
      return new_container;
    }
    

【讨论】:

  • 嗯,没有完整的 C++11 支持(即 VS2012)可以吗?
  • 我猜你必须将typename... 替换为typenames 的正确计数。您提到的类有多个模板参数,它们还有一个分配器。在他们的情况下,您需要编写template&lt;typename,typename&gt; class C,但如果您想将它与具有不同数量模板参数的容器一起使用(比如说std::set),它将不再起作用。
  • @ViktorSehr:我按答案编辑,注意vector/list 带有一个额外的参数allocator,这就是为什么我为C 使用2 个模板参数。
【解决方案2】:

您遇到的问题是您尝试使用C 的方式,它不是一个简单的类型,而是一个类模板。你想要一个模板模板参数:

template<template<typename> class C, typename T0, typename T1>
C<T1> convert_container( C<T0> const &container, T1 value ) {
    C<T1> new_container;
    // Do some stuff...
    return new_container;
}

请注意,这通常不适用于vector 等标准容器,因为它们采用多个模板参数(尽管其中一些是默认的)。如果您使用 C++11,您可以按照 @Jarod42 的建议使用 template&lt;typename...&gt; 而不是 template&lt;typename&gt;

【讨论】:

    【解决方案3】:

    嗯,你的版本看起来有点不干净。我宁愿采用这种方法:

    #include <iterator>
    
    template <class TargetContainer, class OriginalContainer>
    TargetContainer convert_container(const OriginalContainer& inputContainer)
    {
        TargetContainer result;
    
        auto inserter = std::inserter(result, result.begin());
        for (auto& item: inputContainer) {
            *inserter = item;
        }
    
        return result;
    }
    

    ..可以像这样使用:

    std::vector<int> vectorOfInts {1, 2, 3, 4};
    
    auto vectorOfFloats = convert_container<std::vector<float>>(vectorOfInts);
    auto listOfDoubles  = convert_container<std::list<double>>(vectorOfFloats);
    auto setOfLongsWithCustomAlocator = convert_container<std::set<long, myComparator, myAlocator>>(...); //etc
    

    如果您不想使用任何 C++11,只需将 convert_container 中基于 for 的范围替换为正常的 for 循环,并将 auto 声明替换为正确的类型。

    【讨论】:

      猜你喜欢
      • 2015-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多