К сожалению, Visual Studio 2015 не скомпилирует отличное решение TC (из-за некоторой ошибки), поэтому я адаптировал следующее, которое компилируется как в Visual Studio 2015, так и в GCC 5.1.0 (а также обобщается для любого интегрального типа, любой класс и т.д ...). Требовалось заменить только его generate_single
функцию.
#include <iostream>
#include <utility>
#include <type_traits>
// Another way to generate a pack of A's from one P than the above.
template <typename T, template<T...> class Class, T N, T Count, typename Front, typename Output> struct GenerateSingleHelper;
template <typename T, template<T...> class Class, T N, T Count, template <T...> class Z, T... Is, template <typename...> class PackOfPacks, typename... As>
struct GenerateSingleHelper<T, Class, N, Count, Z<Is...>, PackOfPacks<As...>> : GenerateSingleHelper<T, Class, N, Count + 1, Z<Is...>, PackOfPacks<As..., Class<Is..., Count>>> {};
template <typename T, template<T...> class Class, T N, template <T...> class Z, T... Is, template <typename...> class PackOfPacks, typename... As>
struct GenerateSingleHelper<T, Class, N, N, Z<Is...>, PackOfPacks<As...>> {
using type = PackOfPacks<As...>;
};
template <typename T, template<T...> class Class, template <typename...> class PackOfPacks, typename> struct GenerateSingle;
template <typename T, template<T...> class Class, template <typename...> class PackOfPacks, template <T...> class Z, T N, T... Is>
struct GenerateSingle<T, Class, PackOfPacks, Z<N, Is...>> : GenerateSingleHelper<T, Class, N, 0, Z<Is...>, PackOfPacks<>> {};
// Lexicographical comparison of two A's.
template <typename T, typename A1, typename A2> struct Compare; // Determines if A1 < A2.
template <typename T, template <T...> class Pack, T I, T J, T... Is, T... Js>
struct Compare<T, Pack<I, Is...>, Pack<J, Js...>> : std::integral_constant<bool, I < J> {};
template <typename T, template <T...> class Pack, T I, T... Is, T... Js>
struct Compare<T, Pack<I, Is...>, Pack<I, Js...>> : Compare<T, Pack<Is...>, Pack<Js...>> {};
template <typename T, template <T...> class Pack, T... Is>
struct Compare<T, Pack<Is...>, Pack<>> : std::false_type {};
template <typename T, template <T...> class Pack, T J, T... Js>
struct Compare<T, Pack<>, Pack<J, Js...>> : std::true_type {}; // J is needed to indicate that Pack<J, Js...> is not empty.
// Merging two sorted packs of A's.
template <typename T, template <typename...> class PackOfPacks, typename PackOfPacks1, typename PackOfPacks2, typename Result = PackOfPacks<>> struct MergeTwoPacks;
template <typename T, template <typename...> class PackOfPacks, typename A1, typename... A1s, typename A2, typename... A2s, typename... Accumulated>
struct MergeTwoPacks<T, PackOfPacks, PackOfPacks<A1, A1s...>, PackOfPacks<A2, A2s...>, PackOfPacks<Accumulated...>> : std::conditional_t<Compare<T, A1, A2>::value,
MergeTwoPacks<T, PackOfPacks, PackOfPacks<A1s...>, PackOfPacks<A2, A2s...>, PackOfPacks<Accumulated..., A1>>,
MergeTwoPacks<T, PackOfPacks, PackOfPacks<A1, A1s...>, PackOfPacks<A2s...>, PackOfPacks<Accumulated..., A2>>> {};
template <typename T, template <typename...> class PackOfPacks, typename... A1s, typename... Accumulated>
struct MergeTwoPacks<T, PackOfPacks, PackOfPacks<A1s...>, PackOfPacks<>, PackOfPacks<Accumulated...>> {
using type = PackOfPacks<Accumulated..., A1s...>; // Since PackOfPacks<A1s...> is already sorted.
};
template <typename T, template <typename...> class PackOfPacks, typename A2, typename... A2s, typename... Accumulated>
struct MergeTwoPacks<T, PackOfPacks, PackOfPacks<>, PackOfPacks<A2, A2s...>, PackOfPacks<Accumulated...>> { // A2 is needed to indicate that PackOfPacks<A2, A2s...> is not empty.
using type = PackOfPacks<Accumulated..., A2, A2s...>; // Since PackOfPacks<A2s...> is already sorted.
};
// Merging any number of sorted packs of A's.
template <typename T, template <typename...> class PackOfPacks, typename... Packs> struct Merge;
template<typename T, template <typename...> class PackOfPacks, typename First, typename Second, typename... Rest>
struct Merge<T, PackOfPacks, First, Second, Rest...> : Merge<T, PackOfPacks, typename MergeTwoPacks<T, PackOfPacks, First, Second>::type, Rest...> {};
template <typename T, template <typename...> class PackOfPacks, typename Last>
struct Merge<T, PackOfPacks, Last> {
using type = Last;
};
// Putting it all together.
template <typename T, template <T...> class Class, template <typename...> class PackOfPacks, typename... Packs>
struct Generate : Merge<T, PackOfPacks, typename GenerateSingle<T, Class, PackOfPacks, Packs>::type...> {};
// Testing.
template <int...> class A {};
template <typename...> struct PackOfPacks;
template <int...> struct P;
int main() {
std::cout << std::boolalpha << std::is_same<
Generate<int, A, PackOfPacks, P<3>, P<5,0>, P<4,0,0>, P<3,0,1>>::type,
PackOfPacks< A<0>, A<0,0>, A<0,0,0>, A<0,0,1>, A<0,0,2>, A<0,0,3>, A<0,1>, A<0,1,0>, A<0,1,1>, A<0,1,2>, A<0,2>, A<0,3>, A<0,4>, A<1>, A<2> >
>::value << '\n'; // true
}
person
prestokeys
schedule
05.09.2015