NSubsets<N, Pack<Types...>>::typemust be a package of packets consisting of all subsets of Types...size N. For example,
NSubsets<2, Pack<int, char, double>>::type
should be
Pack<Pack<int, char>, Pack<int, double>, Pack<char, double>>
One of the methods is simply to take the decision output PowerSetfrom Getting all the subpackages from the package , and then remove every package that does not have size N. But this is too inefficient for large N (and in any case is bad). Here is my idea (inspired by elegant solutions for PowerSet): Suppose we have Pack<A,B,C,D>, and N = 2. Starting with Pack<>, we repeat the types in Pack<A,B,C,D>and add each type as follows: Before adding anything, we have:
Pack<>
Adding A to the previous one (and preserving the previous one as well), we get:
Pack<>, Pack<A>
Adding B to the previous one (and keeping the previous one), we get:
Pack<>, Pack<A>, Pack<B>, Pack<A,B>,
Pack<A,B> 2, , :
Pack<>, Pack<A>, Pack<B>
C ( ), :
Pack<>, Pack<A>, Pack<B>, Pack<C>, Pack<A,C>, Pack<B,C>.
, Pack<A,C>, Pack<B,C>:
Pack<>, Pack<A>, Pack<B>, Pack<C>
D ( ), :
Pack<D>, Pack<A,D>, Pack<B,D>, Pack<C,D>.
2, , ,
Pack<Pack<A,B>, Pack<A,C>, Pack<B,C>, Pack<A,D>, Pack<B,D>, Pack<C,D>>
.
, Pack<> . N 2, . , , false, , ().
, , - , , ,
.
#include <iostream>
#include <type_traits>
template <int, typename> struct IsSize;
template <int N, template <typename...> class P, typename... Types>
struct IsSize<N, P<Types...>> : std::integral_constant<bool, sizeof...(Types) == N> {};
template <int, typename, typename, typename> struct PartitionPacksBySizeHelper;
template <int N, template <typename...> class P, typename... KeptPacks, typename... SizeNPacks>
struct PartitionPacksBySizeHelper<N, P<>, P<KeptPacks...>, P<SizeNPacks...>> {
using not_sizeN_types = P<KeptPacks...>;
using sizeN_types = P<SizeNPacks...>;
};
template <int N, template <typename...> class P, typename First, typename... Rest, typename... KeptPacks, typename... SizeNPacks>
struct PartitionPacksBySizeHelper<N, P<First, Rest...>, P<KeptPacks...>, P<SizeNPacks...>> : std::conditional<IsSize<N, First>::value,
PartitionPacksBySizeHelper<N, P<Rest...>, P<KeptPacks...>, P<SizeNPacks..., First>>,
PartitionPacksBySizeHelper<N, P<Rest...>, P<KeptPacks..., First>, P<SizeNPacks...>>
>::type {};
template <int, typename> struct PartitionPacksBySize;
template <int N, template <typename...> class P, typename... Packs>
struct PartitionPacksBySize<N, P<Packs...>> : PartitionPacksBySizeHelper<N, P<Packs...>, P<>, P<>> {};
template <typename, typename> struct Append;
template <typename T, template <typename...> class P, typename...Types>
struct Append<T, P<Types...>> {
using type = P<Types..., T>;
};
template <int, typename, typename, typename> struct NSubsetsHelper;
template <int N, template <typename...> class P, typename... CurrentPacks, typename... AccumulatedPacks>
struct NSubsetsHelper<N, P<>, P<CurrentPacks...>, P<AccumulatedPacks...>> {
using type = P<AccumulatedPacks...>;
};
template <int N, template <typename...> class P, typename First, typename... Rest, typename... KeptPacks, typename... SizeNPacks>
struct NSubsetsHelper<N, P<First, Rest...>, P<KeptPacks...>, P<SizeNPacks...>>
: NSubsetsHelper<N, P<Rest...>,
typename PartitionPacksBySize<N, P<KeptPacks..., typename Append<First, KeptPacks>::type...>>::not_sizeN_types,
typename PartitionPacksBySize<N, P<KeptPacks..., typename Append<First, KeptPacks>::type...>>::sizeN_types> {};
template <int, typename> struct NSubsets;
template <int N, template <typename...> class P, typename...Types>
struct NSubsets<N, P<Types...>> : NSubsetsHelper<N, P<Types...>, P<P<>>, P<>> {};
template <typename...> struct Pack {};
int main() {
std::cout << std::boolalpha << std::is_same< NSubsets<2, Pack<int, char, double>>::type,
Pack<Pack<int, char>, Pack<int, double>, Pack<char, double>>
>::value << std::endl;
}
, , , false. , , , . ?
:
typename PartitionPacksBySize<N, P<KeptPacks..., typename Append<First, KeptPacks>::type...>>::sizeN_types>
typename Merge<P<SizeNPacks...>, typename PartitionPacksBySize<N, P<KeptPacks..., typename Append<First, KeptPacks>::type...>>::sizeN_types>::type
- , N , N ?