【问题标题】:defining a variadic coordinate (tuple) type in C++17?在 C++17 中定义可变坐标(元组)类型?
【发布时间】:2019-01-09 00:11:48
【问题描述】:

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

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

我想让CoordT&lt;3&gt;::coord_type 成为 3 维坐标类型:

std::tuple<double, double, double>

.

但我不知道如何使用模板编程生成N重复doubles。

谁能帮忙解释一下怎么写?

【问题讨论】:

  • @Justin 好点。谢谢。

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


【解决方案1】:

使用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

【讨论】:

  • 谢谢!您能否添加一个关于如何使用 foo 函数创建双精度元组的示例?
  • @tinlyx 检查 coliru 链接
【解决方案2】:

如果您实际上不需要std::tuple,而只需要像元组一样的东西,请使用std::array

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

std::array 具有 std::get&lt;I&gt;std::tuple_sizestd::tuple_element 的重载。大多数接受元组元素的库和语言工具都将支持std::array,例如std::applystructured bindings

【讨论】:

    【解决方案3】:

    来不及玩了?

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

    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, "!" );
     }
    

    【讨论】:

      【解决方案4】:

      一个非常简洁的方法是使用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 typesstd::array,但不保证。但是,我检查了supports this 的每个实现。

      【讨论】:

        猜你喜欢
        • 2018-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-17
        • 1970-01-01
        • 1970-01-01
        • 2015-06-27
        • 2017-10-11
        相关资源
        最近更新 更多