Это очень сложный (для меня как минимум). Я начну с обсуждения более простой задачи, которую я уже решил. ExpandPacks<Packs...>::type
- это пакет всех упаковок, полученных из одного типа из каждой упаковки в Packs...
. НапримерПолучение пакета пакетов
ExpandPacks<P<int, char>, P<bool, double, long>>::type
является
P< P<int, bool>, P<int, double>, P<int, long>, P<char, bool>, P<char, double>, P<char, long> >
Я уже написал код, чтобы сделать это для любого количества пакетов:
#include <iostream>
#include <type_traits>
template <typename T, typename Pack> struct Prepend;
template <typename...> struct Merge;
template <typename T, template <typename...> class P, typename... Ts>
struct Prepend<T, P<Ts...>> {
using type = P<T, Ts...>;
};
template <typename Pack>
struct Merge<Pack> {
using type = Pack;
};
template <template <typename...> class P, typename... Ts, typename... Us>
struct Merge<P<Ts...>, P<Us...>> {
using type = P<Ts..., Us...>;
};
template <typename First, typename... Rest>
struct Merge<First, Rest...> : Merge<First, typename Merge<Rest...>::type> {};
template <typename... Packs> struct ExpandPacks;
template <typename T, typename Pack> struct ExpandPacksHelper;
template <typename T, typename PackOfPacks> struct ExpandPacksHelper2;
template <typename Pack, typename PackOfPacks> struct ExpandPacksHelper3;
template <template <typename...> class P, typename T, typename... Ts>
struct ExpandPacksHelper<T, P<Ts...>> {
using type = P<P<T, Ts>...>;
};
template <template <typename...> class P, typename T, typename... Packs>
struct ExpandPacksHelper2<T, P<Packs...>> {
using type = P<typename Prepend<T, Packs>::type...>;
};
template <template <typename...> class P, typename... Ts, typename... Packs>
struct ExpandPacksHelper3<P<Ts...>, P<Packs...>> : Merge<typename ExpandPacksHelper2<Ts, P<Packs...>>::type...> {};
template <template <typename...> class P, typename... Ts, typename Pack>
struct ExpandPacks<P<Ts...>, Pack> : Merge<typename ExpandPacksHelper<Ts, Pack>::type...> {};
template <typename First, typename... Rest>
struct ExpandPacks<First, Rest...> : ExpandPacksHelper3<First, typename ExpandPacks<Rest...>::type> {};
// Testing
template <typename...> struct P;
int main() {
std::cout << std::boolalpha << std::is_same<
typename ExpandPacks<P<int, char>, P<bool, double, long>>::type,
P< P<int, bool>, P<int, double>, P<int, long>, P<char, bool>, P<char, double>, P<char, long> >
>::value << '\n'; // true
std::cout << std::is_same<
typename ExpandPacksHelper3<P<short, float>, P< P<int, bool>, P<int, double>, P<int, long>, P<char, bool>, P<char, double>, P<char, long> >>::type,
P< P<short, int, bool>, P<short, int, double>, P<short, int, long>, P<short, char, bool>, P<short, char, double>, P<short, char, long>, P<float, int, bool>, P<float, int, double>, P<float, int, long>, P<float, char, bool>, P<float, char, double>, P<float, char, long> >
>::value << '\n'; // true
std::cout << std::is_same<
typename ExpandPacks<P<short, float>, P<int, char>, P<bool, double, long>>::type,
P< P<short, int, bool>, P<short, int, double>, P<short, int, long>, P<short, char, bool>, P<short, char, double>, P<short, char, long>, P<float, int, bool>, P<float, int, double>, P<float, int, long>, P<float, char, bool>, P<float, char, double>, P<float, char, long> >
>::value << '\n'; // true
std::cout << std::is_same<
typename ExpandPacks<P<int, bool>, P<short, float>, P<int, char>, P<bool, double, long>>::type,
P< P<int, short, int, bool>, P<int, short, int, double>, P<int, short, int, long>, P<int, short, char, bool>, P<int, short, char, double>, P<int, short, char, long>, P<int, float, int, bool>, P<int, float, int, double>, P<int, float, int, long>, P<int, float, char, bool>, P<int, float, char, double>, P<int, float, char, long>,
P<bool, short, int, bool>, P<bool, short, int, double>, P<bool, short, int, long>, P<bool, short, char, bool>, P<bool, short, char, double>, P<bool, short, char, long>, P<bool, float, int, bool>, P<bool, float, int, double>, P<bool, float, int, long>, P<bool, float, char, bool>, P<bool, float, char, double>, P<bool, float, char, long> >
>::value << '\n'; // true
}
Но теперь я хочу, чтобы обобщить это. Вместо того, чтобы всегда выбирать только один тип из каждого пакета, нужно выбрать N типов из каждого пакета, где N - параметр шаблона. Если N превышает размер определенного пакета, просто возьмите все типы из этого пакета. Порядок типов из каждой упаковки должен быть сохранен. Но я полностью застрял здесь. Кроме того, я не указываю какой-либо конкретный порядок выпущенных пакетов, что также затрудняет тестирование. Ниже приведен пример:
ExpandPacks<2, P<int, char, short>, P<bool, double, long>>::type
есть до порядка пакетов,
P< P<int, char, bool, double>, P<int, char, bool, long>, P<int, char, double, long>,
P<int, short, bool, double>, P<int, short, bool, long>, P<int, short, double, long>,
P<char, short, bool, double>, P<char, short, bool, long>, P<char, short, double, long> >
Пакеты 4, полученные с 2 из P<int, char, short>
и 2 из P<bool, double, long>
. Я мог бы альтернативно определить
ExpandPacks<std::index_sequence<2,1>, P<int, char, short>, P<bool, double, long>>::type
означает взять 2 из P<int, char, short>
и 1 из P<bool, double, long>
, что должно быть легко расширение после того, как первая проблема решается (или решить этот сразу, который будет решать оба вопроса). Поскольку порядок выводимых пачек не указан, я думаю, самый простой способ проверить вывод, чтобы проверить, что
ExpandPacks<1, P<int, char>, P<bool, double, long>>::type
или в качестве альтернативы,
ExpandPacks<std::index_sequence<1,1>, P<int, char>, P<bool, double, long>>::type
является
P< P<int, bool>, P<int, double>, P<int, long>, P<char, bool>, P<char, double>, P<char, long> >
так это должно свести к версии, которую я уже решил. Я буду предлагать щедрость, если никто не сможет так быстро решить эту проблему. Благодарю.
Update: Для целей тестирования, я просто написал программу, чтобы проверить, если два пакета типов равны друг другу с точностью до перестановки типов: http://ideone.com/zb7NA7 Это может быть помощь в тестах с выходом пакеты не указаны в каком-либо конкретном порядке здесь.
Вы можете добавить пример? –
@Piotr Skotnicki Пример добавлен в вопрос. – prestokeys