从具有相同容器类型但不同value_type的容器生成新类型

时间:2015-11-20 13:41:31

标签: c++ templates c++11 c++14 template-meta-programming

给定一个容器,例如std::list<T>std::vector<T>,我想分别在我不知道容器的情况下生成新类型std::list<NewT>std::vector<NewT>std::liststd::vector)提前。

我当前(但failing)尝试的内容如下:

#include <list>
#include <vector>

template<class Cont, class NewT> struct SameContNewT : public std::false_type
{};

template<class T, class Alloc, class NewT>
struct SameContNewT<std::list<T, Alloc>, NewT>
{ typedef typename std::list<NewT> type; };

template<class T, class Alloc, class NewT>
struct SameContNewT<std::vector<T, Alloc>, NewT>
{ typedef typename std::vector<NewT> type; };

int main()
{
    typedef std::list<int> IntList;
    typedef std::list<float> FloatList;
    typedef SameContNewT<IntList, float> FloatListToo;
    static_assert(std::is_same<FloatListToo, FloatList>::value, "No.");
}

如何实现理想的行为?

3 个答案:

答案 0 :(得分:3)

稍后会出现一些模板模板参数...

template <class T, class NewP>
struct SameContNewT;

template <template <class...> class T, class... TPs, class NewP>
struct SameContNewT<T<TPs...>, NewP> {
    using type = T<NewP>;
};

Live on Coliru

这会丢弃原始类型的所有模板参数,例如标准容器的分配器。这些内容需要更多参与,因为您无法重用T的分配器,这很可能std::allocator<typename T::value_type>并且不适合分配NewT& #39; S

答案 1 :(得分:3)

您想要的类型不是SameContNewT<IntList, float>,而是嵌套类型type。您可以使用

直接解决此问题
typedef SameContNewT<IntList, float>::type FloatListToo;

...或使用别名模板:

template <typename Cont, typename New>
using SameContNew =  typename SameContNewT<Cont, New>::type;

...并放弃T

如果你想得到花哨并为大多数任意容器做技巧,你也可以使用类似的东西:

template <template <typename...> class Cont, typename... T, typename New>
struct SameContNewT<Cont<T...>, New>
{ typedef Cont<New> type; };

但是,使用此专业化只会使方法更加通用。它无法解决原始问题。

答案 2 :(得分:1)

template<class Z, class...Ts>
struct rebind_types;
template<class Z, class...Ts>
using rebind_types_t=typename rebind_types<Z,Ts...>;
template<template<class...>class Z, class...Us, class...Ts>
struct rebind_types<Z<Us...>, Ts...>{
  using type=Z<Ts...>;
};

现在我们得到:

typedef std::list<int> IntList;
typedef std::list<float> FloatList;
typedef rebind_types_t<IntList, float> FloatListToo;
static_assert(std::is_same<FloatListToo, FloatList>::value, "No.");

我们可以将多个类型参数传递给rebind_types_t。我们“传递”传递的模板实例,并给它新的参数。

对于特定于容器的版本,您必须了解分配器等的哪些参数(分配器有哪些方法可以反弹到新类型)。处理关联容器的比较器和散列之类的东西变得棘手。