我可以退回不同类型的模板化容器吗?

时间:2014-02-14 15:10:00

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

如何创建一个行为如此的函数?我似乎无法正确声明返回类型。

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

3 个答案:

答案 0 :(得分:6)

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

  • 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;
    }
    

答案 1 :(得分:1)

您遇到的问题是您尝试使用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<typename...>代替template<typename>

答案 2 :(得分:1)

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

#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,只需使用正常的for循环替换convert_container中的范围,并使用正确的类型替换auto声明。