在C ++ 17中定义可变参量(元组)类型?

时间:2019-01-09 00:11:49

标签: c++ tuples c++17 variadic-templates template-meta-programming

我想定义一个可变参数元组类型来表示坐标。例如,对于某些魔术类型:

template <unsigned int N>
struct CoordT {
  typedef std::tuple<_some_magic_> coord_type;
};

我想将CoordT<3>::coord_type设为3维坐标类型:

std::tuple<double, double, double>

但是我不知道如何使用模板编程来生成N个重复的double

有人可以帮忙解释一下怎么写吗?

4 个答案:

答案 0 :(得分:3)

使用std::make_integer_sequence生成适当长度的包,然后将元素映射为双精度:

template <size_t n>
struct TupleOfDoubles {
    template <size_t... i>
    static auto foo(std::index_sequence<i...>) {
        return std::make_tuple(double(i)...);
    }
    using type = decltype(foo(std::make_index_sequence<n>{}));
};

http://coliru.stacked-crooked.com/a/7950876813128c55

答案 1 :(得分:2)

如果您实际上不需要std::tuple,而只需要类似元组的内容,请使用std::array

template <unsigned int N>
struct CoordT {
  typedef std::array<double, N> coord_type;
};

std::array具有std::get<I>std::tuple_sizestd::tuple_element的重载。大多数接受类似元组元素的库和语言设施都将支持std::array,例如std::applystructured bindings

答案 2 :(得分:0)

玩太晚了吗?

如果可以接受声明(不需要定义),则可变参数模板函数如下所示

template <std::size_t ... Is>
constexpr auto toIndexSeq (std::index_sequence<Is...> a)
   -> decltype(a);

并且coord_type是在CoordT专业化中定义的,则可以将其编写如下

template <std::size_t N,
          typename = decltype(toIndexSeq(std::make_index_sequence<N>{}))>
struct CoordT;

template <std::size_t N, std::size_t ... Is>
struct CoordT<N, std::index_sequence<Is...>>
 { using coord_type = std::tuple<decltype((void)Is, 0.0)...>; };

以下是完整的C ++ 14编译示例

#include <tuple> 
#include <type_traits> 

template <std::size_t ... Is>
constexpr auto toIndexSeq (std::index_sequence<Is...> a)
   -> decltype(a);

template <std::size_t N,
          typename = decltype(toIndexSeq(std::make_index_sequence<N>{}))>
struct CoordT;

template <std::size_t N, std::size_t ... Is>
struct CoordT<N, std::index_sequence<Is...>>
 { using coord_type = std::tuple<decltype((void)Is, 0.0)...>; };


int main()
 {
   using t0 = std::tuple<double, double, double, double>;
   using t1 = typename CoordT<4u>::coord_type;

   static_assert( std::is_same<t0, t1>::value, "!" );
 }

答案 3 :(得分:0)

一种非常简洁的方法是使用std::tuple_catstd::array

template <unsigned int N>
struct CoordT {
  using coord_type = decltype(std::tuple_cat(std::array<double, N>{}));
};

std::tuple_catallowed to support tuple-like types,例如std::array,但不能保证。但是,我检查了supports this的每个实现。