假设您有类似
的内容template <typename, typename, int, typename, int, typename...> struct P
并且您只想反转typename...
部分。现在您已经编写了通用的反向转换:
// Reverse<Pack<Types...>>::type is Pack<Types'...>, where Types'... is Types... reversed.
template <typename, typename> struct ReverseHelper;
template <template <typename...> class P, typename Pack>
struct ReverseHelper<P<>, Pack> {
using type = Pack;
};
template <template <typename...> class P, typename First, typename... Rest, typename... Types>
struct ReverseHelper<P<First, Rest...>, P<Types...>> : ReverseHelper<P<Rest...>, P<First, Types...>> {};
template <typename> struct Reverse;
template <template <typename...> class P, typename... Types>
struct Reverse<P<Types...>> : ReverseHelper<P<Types...>, P<>> {};
当然,我们可以用template <typename, typename, int, typename, int, typename...> class P
改写上面的内容,即:
template <typename, typename> struct ReverseHelper1;
template <template <typename, typename, int, typename, int, typename...> class P,
typename U, typename V, int M, typename W, int N, typename Pack>
struct ReverseHelper1<P<U,V,M,W,N>, Pack> {
using type = Pack;
};
template <template <typename, typename, int, typename, int, typename...> class P,
typename U, typename V, int M, typename W, int N, typename First, typename... Rest, typename... Types>
struct ReverseHelper1<P<U,V,M,W,N, First, Rest...>, P<Types...>> : ReverseHelper<P<U,V,M,W,N, Rest...>, P<First, Types...>> {};
template <typename> struct Reverse1;
template <template <typename, typename, int, typename, int, typename...> class P,
typename U, typename V, int M, typename W, int N, typename... Types>
struct Reverse1<P<U,V,M,W,N, Types...>> : ReverseHelper1<P<U,V,M,W,N, Types...>, P<U,V,M,W,N>> {};
请注意我们只是在重复?如果我们想要做同样的部分反转事情,那么我们必须一次又一次地为其他模板签名做这件事。那么如何使用原始Reverse
本身来避免所有这些重复呢?
例如,假设我们有
template <typename> struct Foo;
template <typename> struct Bar;
template <template <typename, typename, int, typename, int, typename...> class P,
typename U, typename V, int M, typename W, int N, typename... Args>
struct Foo<P<U,V,M,W,N, Args...>> {};
让Foo<P<U,V,M,W,N, Args...>>
来自Bar<P<U,V,M,W,N, ArgsReversed...>>
。如何使用上面定义的Reverse
完成此操作?
注意,它与
不一样template <template <typename, typename, int, typename, int, typename> class P,
typename U, typename V, int M, typename W, int N,
template <typename...> class Q, typename... Args>
struct Foo<P<U,V,M,W,N, Q<Args...>>> : Bar<P<U,V,M,W,N, typename Reverse<Q<Args...>>::type>> {};
虽然我怀疑完成它是做了类似的事情。当然,倒车只是一个例子。我们希望重用任何转换,只对部分(任何)较大的模板结构进行相同的转换。
答案 0 :(得分:1)
简单的方法是停止使用int
作为模板的参数。
除此之外,您可以为类和int类型的特定模式编写元函数,并且&#34; lift&#34;模板和实例都是关于类(其中int
被integral_constant
替换),并对它们进行操作(写入&#34; N类型之后的反向类型&#34;以完成相反的操作)。
除此之外,我们可以为您的特定模式提供代码。
template<class...>struct types{using type=types;};
namespace details {
template<class T, class types>
struct replace_tail;
template<class T, class types>
using replace_tail_t = typename replace_tail<T,types>::type;
template<class T>
struct get_tail;
template<class T>
using get_tail_t = typename get_tail<T,types>::type;
template<template <class, class, int, class, int, class...> class P,
class A, class B, int C, class D, int E, class...Fs,
class... Ts
>
struct replace_tail<P<A,B,C,D,E,Fs...>,types<Ts...>> {
using type = P<A,B,C,D,E,Ts...>;
};
template<template <class, class, int, class, int, class...> class P,
class A, class B, int C, class D, int E, class...Fs
>
struct get_tail<P<A,B,C,D,E,Fs...>>:types<Fs...>{};
template<class T>
using reverse_t = ReverseHelper<T>::type;
template<class T>
using reverse_tail = replace_tail_t < T, reverse_t<get_tail_t<T>> >;
}
using details::reverse_tail;
可能包含语法错误。计划是将其分为三部分。
首先,扭转一个包(你已经写过了)。
第二,提取&#34;尾巴&#34;从实例转换为包的参数。
第三,取代&#34;尾巴&#34;与另一包的争论。
连在一起,我们扭转尾巴。对get_tail_t
replace_tail_t
参数的新模式进行专门化template
和reverse_tail_t
会使{{1}}&#34;正常工作&#34;。
答案 1 :(得分:-1)
让我们制作一个类型列表:
template <typename...> struct typelist { };
您可以获得类型列表的第N种类型:
template <size_t N, typename> struct typelist_get;
template <typename T, typename ...Ts>
struct typelist_get<0, typelist<T, Ts...>>
{
using type = T;
};
template <size_t N, typename T, typename ...Ts>
struct typelist_get<N, typelist<T, Ts...>>
: typelist_get<N - 1, typelist<Ts...>>
{ };
您可以撤消类型列表:
template <typename, typename> struct reverse_helper;
template <typename T, typename ...Ts, typename ...Rs>
struct reverse_helper<typelist<T, Ts...>, typelist<Rs...>>
: reverse_helper<typelist<Ts...>, typelist<T, Rs...>>
{ };
template <typename ...Rs>
struct reverse_helper<typelist<>, typelist<Rs...>>
{
using type = typelist<Rs...>;
};
template <typename T> struct typelist_reverse
: reverse_helper<T, typelist<>>
{ };
我们还需要index_sequence:
template <size_t...> struct index_sequence;
以及为给定N建立index_sequence<0, 1, ..., N - 1>
的方法:
template <std::size_t N, std::size_t ...I>
struct index_sequence_builder
{
using type = typename index_sequence_builder<N - 1, N - 1, I...>::type;
};
template <std::size_t ... I>
struct index_sequence_builder<0, I...>
{
using type = index_sequence<I...>;
};
template <std::size_t N>
using make_index_sequence = typename index_sequence_builder<N>::type;
假设我们有一些可变参数模板类Foo
:
template <typename ...Ts> struct Foo { };
然后我们可以按如下方式将其反转:
template <typename, typename> struct reverse_foo_impl;
template <typename ...Ts, size_t ...I>
struct reverse_foo_impl<Foo<Ts...>, index_sequence<I...>>
{
using TL = typelist<Ts...>;
using RTL = typename typelist_reverse<TL>::type;
using type = Foo<typename typelist_get<I, RTL>::type...>;
};
template <typename> struct reverse_foo;
template <typename...Ts>
struct reverse_foo<Foo<Ts...>>
: reverse_foo_impl<Foo<Ts...>, make_index_sequence<sizeof...(Ts)>>
{ };
此处,TL
是Foo
的模板参数作为类型列表,RTL
是相反的类型列表。要将模板参数作为包提取,我们需要创建类似typelist_get<0, RTL>::type, typelist_get<1, RTL>::type, ..., typelist_get<N - 1, RTL>::type
的内容。这是使用索引序列完成的,其中扩展w.r.t. I
完全重新创建了这种模式。
最后我们可以像这样使用它:
using T = Foo<int, char, double>;
using R = reverse_foo<T>::type;
static_assert(std::is_same<Foo<double, char, int>, R>::value, ":(");