【问题标题】:Convert static constexpr array to template parameter in C++11在 C++11 中将静态 constexpr 数组转换为模板参数
【发布时间】:2019-04-10 01:26:11
【问题描述】:

假设我们有一个constexpr 数组,如下所示:

static constexpr unsigned int a[] = {2, 8, ... ,6}; // N element

我想将此数组用作模板参数包:

typedef SomeTemplatedStruct<a[0], a[1], ... ,a[N - 1]> tmp;

在 C++14 中可以这样做,正如 here 所解释的那样。但是,我未能将该代码转换为 C++11。任何帮助表示赞赏。

【问题讨论】:

  • 哪一部分对您有问题? index_sequence ?
  • 是的,同时也希望能找到更简洁的方式。
  • implementation-c14-make-integer-sequence 的示例,链接的解决方案似乎足够简洁 IMO。

标签: c++ c++11 templates variadic-templates template-meta-programming


【解决方案1】:

如果您已经打算自己推出,则无需实现整数序列助手,因为我们可以使用已经展开的包的大小作为下一个元素的索引,以便在递归期间从数组中取出:

template <typename A, A& a, typename U = typename std::remove_reference<decltype(a[0])>::type, bool = true, U... unpack>
struct unravel;

template <typename T, int N, T (&a)[N], typename U, U... unpack>
struct unravel<T[N], a, U, false, unpack...>
{
    template <template <U...> class Thingie>
    using into = Thingie<unpack...>;
};

template <typename T, int N, T (&a)[N], typename U, U... unpack>
struct unravel<T[N], a, U, true, unpack...> : unravel<T[N], a, U, (sizeof...(unpack) + 1 < N), unpack..., a[sizeof...(unpack)]> {};

用法:

struct Blub
{
    static constexpr unsigned int a[] = {2, 8, 5, 7, 6};
};

template <unsigned int...>
struct TheThingToMake {};

void test()
{
    typename unravel<decltype(Blub::a), Blub::a>::into<TheThingToMake> blub;
}

live example

注意:这不适用于大小为 0 的数组,但它们是非标准的,而且我想,无论如何,这并不是一个真正有趣的用例……

【讨论】:

    【解决方案2】:

    我能想象的最好的方法是开发一个 C++11 替代 std::index_sequencestd::make_index_sequence 并应用您链接的 C++14 解决方案。

    但如果你避免它,你可以使用递归。

    给出一个自制的整数序列

    template <typename T, T...>
    struct myIntegerSequence
     { };
    

    还有一个辅助结构mot_h(“制作输出模板助手”)

    template <typename T, T, std::size_t, typename>
    struct mot_h;
    
    // recursive version
    template <typename T, std::size_t N, const T(&A)[N], std::size_t Pos, T ... ts>
    struct mot_h<const T(&)[N], A, Pos, myIntegerSequence<T, ts...>>
       : mot_h<const T(&)[N], A, Pos+1u, myIntegerSequence<T, ts..., A[Pos]>>
     { };
    
    // ground case
    template <typename T, std::size_t N, const T(&A)[N], T ... ts>
    struct mot_h<const T(&)[N], A, N, myIntegerSequence<T, ts...>>
     { using type = myIntegerSequence<T, ts...>; };
    

    你可以写如下模板output

    template <typename T, T inp>
    using output = typename mot_h<T, inp, 0u,
       myIntegerSequence<
          typename std::remove_const<
             typename std::remove_reference<decltype(inp[0])>::type>::type>
             >::type;
    

    以下是一个完整的C++11编译示例

    #include <type_traits>
    
    template <typename T, T...>
    struct myIntegerSequence
     { };
    
    constexpr int input[] = { 2, 3, 5, 7, 11, 13, 17, 19 };
    
    template <std::size_t N, typename T, const T (&A)[N]>
    struct foo
     { };
    
    template <typename T, T, std::size_t, typename>
    struct mot_h;
    
    template <typename T, std::size_t N, const T(&A)[N], std::size_t Pos, T ... ts>
    struct mot_h<const T(&)[N], A, Pos, myIntegerSequence<T, ts...>>
       : mot_h<const T(&)[N], A, Pos+1u, myIntegerSequence<T, ts..., A[Pos]>>
     { };
    
    template <typename T, std::size_t N, const T(&A)[N], T ... ts>
    struct mot_h<const T(&)[N], A, N, myIntegerSequence<T, ts...>>
     { using type = myIntegerSequence<T, ts...>; };
    
    template <typename T, T inp>
    using output = typename mot_h<T, inp, 0u,
       myIntegerSequence<
          typename std::remove_const<
             typename std::remove_reference<decltype(inp[0])>::type>::type>
             >::type;
    
    int main ()
     {
       using target = myIntegerSequence<int, 2, 3, 5, 7, 11, 13, 17, 19>;
    
       static_assert( std::is_same<output<decltype((input)), input>,
                                   target>::value, "!" );
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-21
      • 1970-01-01
      • 2020-08-26
      • 1970-01-01
      • 2020-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多