2

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

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
4

3 回答 3

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;
    }
    
于 2014-02-14T15:16:26.400 回答
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>.

于 2014-02-14T15:21:51.700 回答
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 in 的范围替换为convert_container普通的 for 循环,并将auto声明替换为正确的类型。

于 2014-02-14T15:28:40.257 回答