2013-08-15 2 views
1

Рассмотрим следующий код:Преобразовать скалярная + станд :: массив + станд :: кортеж в большой кортеж

template <class Scalar, class Array, class Tuple> 
class Test {}; 

где Array является std::array и Tuple является std::tuple. В этом классе у меня будет много SFINAE, и я бы хотел создать большой кортеж под названием Types, который будет содержать полный список типов. Это позволит мне проверить некоторые условия с вариационными списками.

Таким образом, задача состоит в том, чтобы создать тип, который будет иметь следующее поведение. Если:

  • Scalar = int
  • Array = std::array<double, 3>
  • Tuple = std::tuple<char, float, std::string>

Тогда:

  • Types = std::tuple<int, double, double, double, char, float, std::string>

, который является конкатенацией внутренних данных Scalar, Array и Tuple.

Как это сделать?

+0

вы хотите объединить массивы с кортежами – aaronman

+3

[ 'станд :: tuple_cat'] (HTTP://coliru.stacked-crooked.com/view?id=8dbb18afcd1077d40ba97730bb58feca-0ef62b711c3b4aca94c9bcb419c937b3)~ – Xeo

ответ

2

Это похоже на работу:

template<typename T1, typename T2> 
struct concat_tuples; 

template<typename... T1, typename... T2> 
struct concat_tuples<std::tuple<T1...>, std::tuple<T2...>> 
{ 
    using type = std::tuple<T1..., T2...>; 
}; 

// n_tuple<int, 3>::type == std::tuple<int, int, int> 
template<typename T, size_t n> 
struct n_tuple; 

template<typename T> 
struct n_tuple<T, 0> 
{ 
    using type = std::tuple<>; 
}; 

template<typename T, size_t n> 
struct n_tuple 
{ 
    using type = typename concat_tuples< 
        typename n_tuple<T, n-1>::type, 
        std::tuple<T> 
       >::type; 
}; 

template <class Scalar, class Array, class Tuple> 
struct Test; 

template <class Scalar, typename T, size_t n, typename... Ts> 
struct Test<Scalar, std::array<T, n>, std::tuple<Ts...>> 
{ 
    using type = typename concat_tuples< 
        typename concat_tuples< 
         std::tuple<Scalar>, 
         typename n_tuple<T, n>::type 
        >::type, 
        std::tuple<Ts...> 
       >::type; 
}; 

Живая демонстрация here.

1

Использование частичной специализации выводить типы, и tuple_cat комментарий XEO, чтобы поставить их вместе (Live at Coliru:

template <typename ArrayType, std::size_t ArraySize, typename... Fields> 
struct ArrayTuple : ArrayTuple<ArrayType, ArraySize-1, ArrayType, Fields...> {}; 
template <typename ArrayType, typename... Fields> 
struct ArrayTuple<ArrayType, 0, Fields...> { 
    using type = std::tuple<Fields...>; 
}; 

template <typename, typename, typename> class Test; 

template <typename Scalar, typename ArrayType, std::size_t ArraySize, typename... Fields> 
class Test<Scalar, std::array<ArrayType, ArraySize>, std::tuple<Fields...>> { 
public: 
    // Modified tuple_cat code from Xeo's comment: 
    using Tuple = std::tuple<Fields...>; 
    using Types = decltype(
     std::tuple_cat(std::tuple<Scalar>(), 
        typename ArrayTuple<ArrayType, ArraySize>::type(), 
        std::declval<Tuple>())); 
}; 
+1

FWIW, я не вижу необходимости в частичной специализации здесь. Я просто использовал 'use' mirror его параметры шаблона. – Xeo

+0

@Xeo Это SFINAE бедного человека, чтобы исключить не-массивы и кортежи из соответствующих параметров. – Casey

+0

Я не знал, что 'tuple_cat' расширяет' std: : array' вот так. Ницца. – jrok