给定一个容器,例如std::list<T>
或std::vector<T>
,我想分别在我不知道容器的情况下生成新类型std::list<NewT>
或std::vector<NewT>
(std::list
或std::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.");
}
如何实现理想的行为?
答案 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>;
};
这会丢弃原始类型的所有模板参数,例如标准容器的分配器。这些内容需要更多参与,因为您无法重用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
。我们“传递”传递的模板实例,并给它新的参数。
对于特定于容器的版本,您必须了解分配器等的哪些参数(分配器有哪些方法可以反弹到新类型)。处理关联容器的比较器和散列之类的东西变得棘手。