Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Pack<Pack<int, char, double>, Pack<int, double, char>, Pack<char, int, double>, Pack<char, double, int>, Pack<double, int, char>, Pack<double, char, int>>
- #include <iostream>
- #include <type_traits>
- template <typename, typename, typename...> struct RemoveFirstTypeFound;
- template <typename T> struct Identity { using type = T; };
- template <typename RemoveMe, template<typename...> class P, typename First, typename... Rest, typename... Types>
- struct RemoveFirstTypeFound<RemoveMe, P<First, Rest...>, Types...> : std::conditional<std::is_same<RemoveMe, First>::value,
- Identity<P<Types..., Rest...>>,
- RemoveFirstTypeFound<RemoveMe, P<Rest...>, Types..., First>
- >::type {};
- template <typename, typename> struct Prepend;
- template <typename T, template <typename...> class P, typename... Types>
- struct Prepend<T, P<Types...>> {
- using type = P<T, Types...>;
- };
- template <typename, typename> struct PrependToEachPack;
- template <typename T, template <typename...> class P, typename... Packs>
- struct PrependToEachPack<T, P<Packs...>> {
- using type = P<typename Prepend<T, Packs>::type...>;
- };
- template <typename, typename> struct Merge;
- template <template <typename...> class P, typename... Types1, typename... Types2>
- struct Merge<P<Types1...>, P<Types2...>> {
- using type = P<Types1..., Types2...>;
- };
- template <typename, typename, typename> struct AllPermutedPacksHelper;
- template <template<typename...> class P, typename Pack, typename... AccumulatedPacks>
- struct AllPermutedPacksHelper<Pack, P<>, P<AccumulatedPacks...>> {
- using type = P<AccumulatedPacks...>;
- };
- template <template<typename...> class P, typename... Types, typename Last>
- struct AllPermutedPacksHelper<P<Types...>, P<Last>, P<>> {
- using type = P<P<Last>>;
- };
- template <template<typename...> class P, typename First, typename Pack1, typename Pack2, typename Pack3, typename Pack4>
- using AllPermutedPacksHelperAlias = AllPermutedPacksHelper<Pack1, Pack2, typename Merge<Pack3,
- typename PrependToEachPack<First, typename AllPermutedPacksHelper<Pack4, Pack4, P<>>::type>::type>::type>;
- template <template<typename...> class P, typename... Types, typename... AccumulatedPacks, typename First, typename... Rest>
- struct AllPermutedPacksHelper<P<Types...>, P<First, Rest...>, P<AccumulatedPacks...>> :
- AllPermutedPacksHelperAlias<P, First, P<Types...>, P<Rest...>, P<AccumulatedPacks...>, typename RemoveFirstTypeFound<First, P<Types...>>::type> {};
- template <typename> struct AllPermutedPacks;
- template <template<typename...> class P, typename... Types>
- struct AllPermutedPacks<P<Types...>> : AllPermutedPacksHelper<P<Types...>, P<Types...>, P<>> {};
- // -----------------------------------------------------------------------------------------------------------------------------------------------
- // Testing
- template <typename...> struct Pack {};
- int main() {
- std::cout << std::boolalpha << std::is_same< AllPermutedPacks<Pack<>>::type,
- Pack<>
- >::value << std::endl; // true
- std::cout << std::is_same< AllPermutedPacks<Pack<int>>::type,
- Pack<Pack<int>>
- >::value << std::endl; // true
- std::cout << std::is_same< AllPermutedPacks<Pack<int, char>>::type,
- Pack<Pack<int, char>, Pack<char, int>>
- >::value << std::endl; // true
- std::cout << std::is_same< AllPermutedPacks<Pack<int, char, double>>::type,
- Pack<Pack<int, char, double>, Pack<int, double, char>, Pack<char, int, double>, Pack<char, double, int>, Pack<double, int, char>, Pack<double, char, int>>
- >::value << std::endl; // true
- }
- #include <type_traits>
- #include <utility>
- namespace utilities {
- template <typename Pack1, typename Pack2> struct merge;
- template <template <typename...> class P, typename... Ts, typename... Us>
- struct merge<P<Ts...>, P<Us...>> {
- using type = P<Ts..., Us...>;
- };
- }
- template <std::size_t R, typename Pack, typename TypesIgnored, typename Output, typename = void> struct nPr_h;
- template <template <typename...> class P, typename First, typename... Rest, typename... TypesIgnored, typename... Output>
- struct nPr_h<0, P<First, Rest...>, P<TypesIgnored...>, P<Output...>> {
- using type = P<P<Output...>>; // Just one single pack (which must be wrapped in P so that the resulting merge will gave all such single packs, rather than a merge of all the types).
- };
- template <std::size_t R, template <typename...> class P, typename TypesIgnored, typename Output>
- struct nPr_h<R, P<>, TypesIgnored, Output> {
- using type = P<>; // No pack can come out of this (permuting R types from nothing).
- };
- template <std::size_t R, template <typename...> class P, typename First, typename... Rest, typename... TypesIgnored, typename... Output>
- struct nPr_h<R, P<First, Rest...>, P<TypesIgnored...>, P<Output...>, std::enable_if_t<(R > sizeof...(Rest) + sizeof...(TypesIgnored))>> {
- using type = P<>; // No pack can come out of this (since there are less types in P<TypesIgnored..., Rest...> than R).
- };
- template <std::size_t R, template <typename...> class P, typename First, typename... Rest, typename... TypesIgnored, typename... Output>
- struct nPr_h<R, P<First, Rest...>, P<TypesIgnored...>, P<Output...>, std::enable_if_t<(R <= sizeof...(Rest) + sizeof...(TypesIgnored) && R != 0)>> : utilities::merge<
- typename nPr_h<R-1, P<TypesIgnored..., Rest...>, P<>, P<Output..., First>>::type, // Case 1: 'First' is in the permuted pack (note that Output..., First are the types in just one pack). Now continue to get R-1 more types from TypesIgnored..., Rest... (which are the remaining available types since 'First' is no longer available for the remaining R-1 types, and the ignored types are now P<> since we are starting a new nPr_h call).
- typename nPr_h<R, P<Rest...>, P<TypesIgnored..., First>, P<Output...>>::type // Case 2: 'First in not in the permuted pack, so try to get R types from Rest... to append to Output... First is appended o TypesIgnored... since it is now among those types not used.
- > { };
- template <std::size_t R, typename Pack> struct nPr;
- template <std::size_t R, template <typename...> class P, typename... Ts>
- struct nPr<R, P<Ts...>> : nPr_h<R, P<Ts...>, P<>, P<>> { };
- // Testing
- template <typename...> struct P;
- int main() {
- static_assert(std::is_same<
- nPr<2, P<int, char, float>>::type,
- P<P<int, char>, P<int, float>, P<char, int>, P<char, float>, P<float, int>, P<float, char>>
- >::value);
- static_assert(std::is_same<
- nPr<3, P<int, char, float, bool>>::type,
- P<P<int, char, float>, P<int, char, bool>, P<int, float, char>, P<int, float, bool>, P<int, bool, char>, P<int, bool, float>, P<char, int, float>, P<char, int, bool>, P<char, float, int>, P<char, float, bool>, P<char, bool, int>, P<char, bool, float>, P<float, int, char>, P<float, int, bool>, P<float, char, int>, P<float, char, bool>, P<float, bool, int>, P<float, bool, char>, P<bool, int, char>, P<bool, int, float>, P<bool, char, int>, P<bool, char, float>, P<bool, float, int>, P<bool, float, char>>
- >::value);
- }
Add Comment
Please, Sign In to add comment