У меня уже есть механизм для вставки конкретного элемента внутрь контейнера, в который он помещается, но я понятия не имею, как создавать комбинации.
Предположим, у вас есть список типов (скажем, A, B, C
) и целое число без знака N
. Я предлагаю using
template <std::size_t N, typename ... Ts>
using Combinations = ???
, который определяется какstd::tuple
, содержащий список std::tuple
s со всеми комбинациями.
Так, например,
Combinations<2u, A, B, C>
становится
std::tuple<
std::tuple<A,A>, std::tuple<A,B>, std::tuple<A,C>,
std::tuple<B,A>, std::tuple<B,B>, std::tuple<B,C>,
std::tuple<C,A>, std::tuple<C,B>, std::tuple<C,C>>
Следующее является полнымпример компиляции C ++ 11
#include <tuple>
#include <vector>
#include <type_traits>
struct A {};
struct B {};
struct C {};
template <typename T, typename ... Ts>
constexpr std::tuple<T, Ts...> addTupleType (std::tuple<Ts...>);
template <typename T, typename ... Ts>
constexpr auto addType ()
-> std::tuple<decltype(addTupleType<T>(std::declval<Ts>()))...>;
template <typename ... Ts, typename ... Us>
constexpr auto getCombinations (std::integral_constant<std::size_t, 0u>,
std::tuple<Ts...> t, std::tuple<Us ...> u)
-> decltype( u );
template <std::size_t N, typename ... Ts, typename ... Us,
typename std::enable_if<(N > 0u), bool>::type = true>
constexpr auto getCombinations (std::integral_constant<std::size_t, N>,
std::tuple<Ts...> t, std::tuple<Us ...>)
-> decltype (getCombinations(
std::integral_constant<std::size_t, N-1u>{}, t,
std::tuple_cat(addType<Ts, Us...>()...)));
template <std::size_t N, typename ... Ts>
using Combinations
= decltype(getCombinations(
std::integral_constant<std::size_t, N-1u>{},
std::declval<std::tuple<Ts...>>(),
std::declval<std::tuple<std::tuple<Ts>...>>()));
template <typename ... Ts>
constexpr auto CombListHelper (std::tuple<Ts...>)
-> std::tuple<std::vector<Ts>...>;
template <typename T>
using CombinationList = decltype(CombListHelper(std::declval<T>()));
int main()
{
using type_1 = Combinations<2u, A, B, C>;
using type_2 = std::tuple<
std::tuple<A,A>, std::tuple<A,B>, std::tuple<A,C>,
std::tuple<B,A>, std::tuple<B,B>, std::tuple<B,C>,
std::tuple<C,A>, std::tuple<C,B>, std::tuple<C,C>>;
static_assert( std::is_same<type_1, type_2>::value, "!" );
using type_3 = CombinationList<Combinations<2u, A, B, C>>;
using type_4 = std::tuple<
std::vector<std::tuple<A,A>>, std::vector<std::tuple<A,B>>,
std::vector<std::tuple<A,C>>, std::vector<std::tuple<B,A>>,
std::vector<std::tuple<B,B>>, std::vector<std::tuple<B,C>>,
std::vector<std::tuple<C,A>>, std::vector<std::tuple<C,B>>,
std::vector<std::tuple<C,C>>>;
static_assert( std::is_same<type_3, type_4>::value, "!" );
}