1

考虑以下代码:

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

哪里Array是 a std::arrayTuple是 a 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>

这是 , 和 的内部数据ScalarArray串联Tuple

怎么做 ?

4

2 回答 2

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;
};

现场演示在这里

于 2013-08-15T22:33:58.310 回答
1

使用部分专业化来推断类型,并使用 Xeo 的tuple_cat评论将它们放在一起(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>()));
};
于 2013-08-15T22:37:21.593 回答