例如,
using NestedPack = Pack<long, char, double, Pack<long, int, short, int>, char, int>;
然后
RemoveFirstFoundFromNestedPack<int, NestedPack>::type
应该给
Pack<long, char, double, Pack<long, short, int>, char, int>
首先,我照顾了一个非嵌套包的情况:
template <typename T> struct Identity { using type = T; };
template <typename, typename, typename...> struct RemoveFirstFoundFromPackHelper;
template <typename RemoveMe, template<typename...> class P, typename... Types>
struct RemoveFirstFoundFromPackHelper<RemoveMe, P<>, Types...> {
using type = P<Types...>;
};
template <typename RemoveMe, template<typename...> class P, typename First, typename... Rest, typename... Types>
struct RemoveFirstFoundFromPackHelper<RemoveMe, P<First, Rest...>, Types...> :
std::conditional<std::is_same<RemoveMe, First>::value,
Identity <P<Types..., Rest...>>,
RemoveFirstFoundFromPackHelper<RemoveMe, P<Rest...>, Types..., First>
>::type {};
template <typename, typename> struct RemoveFirstFoundFromPack;
template <typename RemoveMe, template<typename...> class P, typename... Types>
struct RemoveFirstFoundFromPack<RemoveMe, P<Types...>> : RemoveFirstFoundFromPackHelper<RemoveMe, P<Types...>> {};
经过测试可以正常工作(使用std::is_same
)。但是我对嵌套的情况感到困惑。这是我的最新尝试,给出了错误的结果(尽管我无法追查原因):
template <typename>
struct IsPack : std::false_type {};
template <template<typename...> class P, typename... Types>
struct IsPack<P<Types...>> : std::true_type {};
template <typename...> struct MergePacks;
template <typename Pack>
struct MergePacks<Pack> : Identity<Pack> {};
template <template <typename...> class P, typename... Types1, typename... Types2, typename... Packs>
struct MergePacks<P<Types1...>, P<Types2...>, Packs...> : MergePacks<P<Types1..., Types2...>, Packs...> {};
template <typename, typename, typename> struct RemoveFirstFoundFromNestedPackHelper;
template <typename RemoveMe, template<typename...> class P, typename... Types>
struct RemoveFirstFoundFromNestedPackHelper<RemoveMe, P<>, P<Types...>> {
using type = P<Types...>;
};
template <typename RemoveMe, template<typename...> class P, typename First, typename... Rest, typename... Types>
struct RemoveFirstFoundFromNestedPackHelper<RemoveMe, P<First, Rest...>, P<Types...>> :
std::conditional<std::is_same<RemoveMe, First>::value,
Identity <P<Types..., Rest...>>,
typename std::conditional<IsPack<First>::value,
RemoveFirstFoundFromNestedPackHelper<RemoveMe, P<Rest...>, typename MergePacks<P<Types...>,
typename RemoveFirstFoundFromPack<RemoveMe, First>::type>::type>,
RemoveFirstFoundFromNestedPackHelper<RemoveMe, P<Rest...>, P<Types..., First>>
>::type
>::type {};
template <typename, typename> struct RemoveFirstFoundFromNestedPack;
template <typename RemoveMe, template<typename...> class P, typename... Types>
struct RemoveFirstFoundFromNestedPack<RemoveMe, P<Types...>> :
RemoveFirstFoundFromNestedPackHelper<RemoveMe, P<Types...>, P<>> {};
我知道必须有比这更好的方法。
当然,一旦解决了这个问题,那么从嵌套包中删除所有指定类型的实例就应该是解决方案的一个简单变化(对于非嵌套情况,我已经做到了)。
IsPack
只要它没有非类型参数,您的特征就几乎可以匹配太阳下的每个模板,这是一个非常糟糕的主意。
template <class...> struct Pack {};
template <class, class, class = Pack<>> struct Remove_First;
// First one isn't a pack, and isn't what we are looking for.
template <class R, class F, class...Args1, class...Args2>
struct Remove_First<R, Pack<F, Args1...>, Pack<Args2...>> : Remove_First<R, Pack<Args1...>, Pack<Args2..., F>> {};
// First one is the type we are looking for.
template <class R, class...Args1, class...Args2>
struct Remove_First<R, Pack<R, Args1...>, Pack<Args2...>> { using type = Pack<Args2..., Args1...>; };
// Didn't find the type
template <class R, class...Args>
struct Remove_First<R, Pack<>, Pack<Args...>> { using type = Pack<Args...>; };
// Nested pack: Attempt to remove R from the nested pack
// Use is_same to check if a removal occurred and proceed accordingly
template <class R, class...Args1, class...Args2, class...ArgsNested>
struct Remove_First<R, Pack<Pack<ArgsNested...>, Args1...>, Pack<Args2...>> {
using type = typename std::conditional<
std::is_same<typename Remove_First<R, Pack<ArgsNested...>>::type, Pack<ArgsNested...>>::value,
typename Remove_First<R, Pack<Args1...>, Pack<Args2..., Pack<ArgsNested...>>>::type,
Pack<Args2..., typename Remove_First<R, Pack<ArgsNested...>>::type, Args1...>>::type;
};
// if the type to remove is a Pack, and the first type in the list is a Pack,
// and they are the same pack, then remove it and we are done.
// if they are not the same Pack, then this specialization won't match,
// and we go into the recursion case as normal.
template <class...Args1, class...Args2, class...ArgsNested>
struct Remove_First<Pack<ArgsNested...>, Pack<Pack<ArgsNested...>, Args1...>, Pack<Args2...>> {
using type = Pack<Args2..., Args1...>;
};
template<class R, class Pack>
using remove_first_t = typename Remove_First<R, Pack>::type;
前三个部分专业化处理从非嵌套包装中删除。嵌套包由第四部分专业化处理。它以递归方式对嵌套包执行删除操作。如果删除了一个类型(因此生成的类型与原始的嵌套包类型不同),那么我们就完成了。否则,我们将像往常一样继续处理外包装的其余部分。最终的专业化处理要删除的类型是其Pack
自身的情况,否则,当存在该类型时,第二个和第四个部分专业化将匹配,并且两者都不比另一个专业化,从而导致歧义错误。
演示。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句