在这里,作为一个例子,我将尝试将包中的模板参数向左旋转N,但我希望这也完成嵌套包的每个内包。下面的代码只有在内包是包中的第一个类型时才有效,我需要知道如果它是嵌套的,如何检查包中的每个类型,然后将转换应用于每个类型。 TransformNestedPack
是我正在努力的方向。 PackTransformation
的原因是TransformNestedPack
可以重复用于任何转换(轮换只是我使用的一个例子)。因此,我尝试使用常规转换TransformNestedPack
来完善PackTransformation
。
#include <iostream>
// Rotating a pack N to the left.
template <int, typename> struct Rotate;
template <template <typename...> class P, typename First, typename... Rest>
struct Rotate<0, P<First, Rest...>> {
using type = P<First, Rest...>;
};
template <int N, int K>
struct PositiveModulo : std::integral_constant<int, (N % K + K) % K> {};
template <int N, template <typename...> class P, typename First, typename... Rest>
struct Rotate<N, P<First, Rest...>> :
Rotate<PositiveModulo<N-1, sizeof...(Rest)+1>::value, P<Rest..., First>> {};
enum {Rot, Rev, /* ... */}; // enum values for each type of pack transformation.
template <typename, int, int...> struct PackTransformation;
// Specializations of PackTransformation to carry out each type of pack transformation.
template <template <typename...> class P, int N, typename... Types>
struct PackTransformation<P<Types...>, Rot, N> {
using type = typename Rotate<N, P<Types...>>::type;
};
// Similarly struct PackTransformation<P<Types...>, Rev> will reverse P<Types...>, etc...
// Attempt to have PackTransformation applied to each inner pack in a nested pack:
template <typename, int, int...> struct TransformNestedPack;
// Normal transformation, because the first type is not a pack:
template <template <typename...> class P, typename... Types, int N, int... Parameters>
struct TransformNestedPack<P<Types...>, N, Parameters...> : PackTransformation<P<Types...>, N, Parameters...> {};
// Specialization for when the first type is a pack:
template <template <typename...> class P, typename... Types, typename... Rest, int N, int... Parameters>
struct TransformNestedPack<P<P<Types...>, Rest...>, N, Parameters...> :
PackTransformation<P<typename TransformNestedPack<P<Types...>, N, Parameters...>::type, Rest...>, N, Parameters...> {};
// The problem above is that it checks only the first type. It needs to check EVERY type.
template <typename...> struct Pack {};
int main() {
using NestedPack = Pack<Pack<int, double, char, long>, char, long, short>;
PackTransformation<NestedPack, Rot, 2>::type a; // Rotates NestedPack to the left by 2, but not the inner pack.
std::cout << std::boolalpha << std::is_same< decltype(a),
Pack<long, short, Pack<int, double, char, long>, char>
>::value << std::endl; // true
TransformNestedPack<NestedPack, Rot, 2>::type b;
std::cout << std::is_same< decltype(b),
Pack<long, short, Pack<char, long, int, double>, char>
>::value << std::endl; // true
// The above currently works only if there is one nested pack and that nested pack is the first type.
}
我只需要通过检查每种类型来概括上述内容,如果它是一个包,而不仅仅是第一个。
答案 0 :(得分:2)
首先,不要将TransformNestedPack
的主要模板保留为未定义,如果它不是包,则使其返回不变的类型:
template <typename T, int, int...> struct TransformNestedPack {
using type = T; // do nothing for non-packs
};
然后转换包包括1)以递归方式将TransformNestedPack
应用于包中的每个类型,以及2)将PackTransformation
应用于生成的转换类型包本身。因此:
template <template <typename...> class P, typename... Types, int N, int... Parameters>
struct TransformNestedPack<P<Types...>, N, Parameters...>
: PackTransformation<P<typename TransformNestedPack<Types, N, Parameters...>::type...>,
N, Parameters...> {};