C++ 转换嵌套包的每个内部包
这里,作为一个例子,我将尝试将包中的模板参数向左旋转N,但我希望对嵌套包的每个内部包也这样做。下面的代码仅在内部包是包中的第一个类型时有效,我需要知道如何检查包中的每个类型(如果它是嵌套的),然后将转换应用于每个类型<代码>TransformNestedPack是我正在研究的。C++ 转换嵌套包的每个内部包,c++,templates,variadic,C++,Templates,Variadic,这里,作为一个例子,我将尝试将包中的模板参数向左旋转N,但我希望对嵌套包的每个内部包也这样做。下面的代码仅在内部包是包中的第一个类型时有效,我需要知道如何检查包中的每个类型(如果它是嵌套的),然后将转换应用于每个类型TransformNestedPack是我正在研究的。PackTransformation的原因是TransformNestedPack可以在任何转换中重用(旋转只是我使用的一个示例)。因此,我尝试使用常规转换PackTransformation来完善TransformNestedP
PackTransformation
的原因是TransformNestedPack
可以在任何转换中重用(旋转只是我使用的一个示例)。因此,我尝试使用常规转换PackTransformation
来完善TransformNestedPack
#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.
}
#包括
//向左旋转一个包N。
模板结构旋转;
模板
结构旋转{
使用类型=P;
};
模板
结构正模块:std::积分常数{};
模板
结构旋转:
旋转{};
枚举{Rot,Rev,/*…*/};//每种包转换类型的枚举值。
模板结构包转换;
//包装转换的专业化,以执行每种类型的包装转换。
模板
结构包转换{
使用type=typename旋转::type;
};
//类似地,结构包转换将反转P等。。。
//尝试将PackTransformation应用于嵌套包中的每个内部包:
模板结构转换嵌套包;
//正常转换,因为第一种类型不是包:
模板
struct TransformNestedPack:PackTransformation{};
//第一种类型为包时的专用化:
模板
结构转换嵌套包:
包装转换{};
//上面的问题是它只检查第一种类型。它需要检查每种类型。
模板结构包{};
int main(){
使用NestedPack=Pack;
PackTransformation::type a;//将嵌套包向左旋转2,但不旋转内部包。
std::cout首先,不要让TransformNestedPack
的主模板未定义,而是让它在不是包的情况下返回不变的类型:
template <typename T, int, int...> struct TransformNestedPack {
using type = T; // do nothing for non-packs
};
.看起来像是对某些编译器模板引擎的单元测试。当然,这个优秀的解决方案得到了我的投票。但它不适用于不同的包模板。例如,当我尝试反转pack
时,我没有得到所需的pack
。我的旋转示例也存在同样的问题。这就是使用解决方案中的模板模板P
。@prestokeys它可以很好地处理不同的包类型。问题是,您的代码将std::string
视为一个包,并反转/旋转其模板参数;我只是照着做。好的,用另一个专门化struct TransformNestedPack摆脱了该部分{using type=std::string;};
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...> {};