ExtractEveryPack<Pack>::type is the pack of all "leaf-packs" in Pack. For example, ExtractEveryPack< Pack<double, Pack<int, char>, int, Pack<long, short>> >::type is Pack< Pack<int, char>, Pack<long, short> >. But "outer packs" are not returned. Only the most inner packs (which I'm calling "leaf packs") are extracted. So
ExtractEveryPack<Pack<Pack<int, double>, char, Pack<long, Pack<Pack<int, char>, Pack<char, Pack<double, int>>>, char>, int, Pack<short, int>>>::type,
is
Pack< Pack<int, double>, Pack<int, char>, Pack<double, int>, Pack<short, int>.
My idea: ExtractEveryPack<T>::type is T by default. Then recursively, apply ExtractEveryPack to every type and remove all types that are not packs:
#include <iostream>
template <typename, typename> struct RemoveNonPacksHelper;
template <template <typename...> class P, typename... Accumulated>
struct RemoveNonPacksHelper<P<>, P<Accumulated...>> {
using type = P<Accumulated...>;
};
template <template <typename...> class P, typename First, typename... Rest, typename... Accumulated>
struct RemoveNonPacksHelper<P<First, Rest...>, P<Accumulated...>> : RemoveNonPacksHelper<P<Rest...>, P<Accumulated...>> {};
template <template <typename...> class P, typename... Types, typename... Rest, typename... Accumulated>
struct RemoveNonPacksHelper<P<P<Types...>, Rest...>, P<Accumulated...>> : RemoveNonPacksHelper<P<Rest...>, P<Accumulated..., P<Types...>>> {};
template <typename> struct RemoveNonPacks;
template <template <typename...> class P, typename... Types>
struct RemoveNonPacks<P<Types...>> : RemoveNonPacksHelper<P<Types...>, P<>> {};
template <typename T> struct Identity { using type = T; };
template <typename T>
struct ExtractEveryPack : Identity<T> {}; // Do nothing for non-packs.
// The key idea here, but apparently not correct:
template <template <typename...> class P, typename... Types>
struct ExtractEveryPack<P<Types...>> :
RemoveNonPacks<P<typename ExtractEveryPack<Types>::type...>> {};
// Testing
template <typename...> struct Pack {};
int main() {
std::cout << std::boolalpha << std::is_same<
RemoveNonPacks< Pack<Pack<int, double>, char, Pack<long, double, char>, int, Pack<short, int>> >::type,
Pack<Pack<int, double>, Pack<long, double, char>, Pack<short, int>>
>::value << std::endl; // true
std::cout << std::is_same<
ExtractEveryPack<Pack<Pack<int, double>, char, Pack<long, Pack<Pack<int, char>, Pack<char, Pack<double, int>>>, char>, int, Pack<short, int>>>::type,
Pack< Pack<int, double>, Pack<int, char>, Pack<double, int>, Pack<short, int> >
>::value << std::endl; // false (darn!)
}
What's wrong here? My plan or the implementation of it? What would be a better plan?
Aucun commentaire:
Enregistrer un commentaire