【问题标题】:C++14 compile time std::array with variadic templates带有可变参数模板的 C++14 编译时 std::array
【发布时间】:2016-07-13 14:42:31
【问题描述】:

我想使用 c++14 可变参数模板构建一个编译时查找表。 目前我在那里:

static const unsigned kCount = 5;

template<unsigned Index>
constexpr auto getRow(void)
{
    return std::array<unsigned, 2> { Index, Index * Index };
}

template<unsigned... Indices>
constexpr auto generateTable(std::index_sequence<Indices...>)
{
    return std::array<std::array<unsigned, 2>, sizeof...(Indices)>
    {
        // This is were I'm stuck. How to build a std::array using Indices as template parameter in getRow()?
    };
}

constexpr auto generate(void)
{
    return generateTable(std::make_index_sequence<kCount>{});
}

我希望表格位于std::array 中。每行包含一个 std::array 和 2 列。我被困在generateTable() 中,我需要以某种方式将我的索引作为模板参数传递给getRow()

这是否可以使用std::integer_sequence 和模板参数包扩展来实现,还是我需要自己实现递归?

getRow() 被简化了 - 值类型实际上来自模板类型。Index * Index 只是一个占位符。我需要知道如何使用参数包扩展调用getRow()。)

【问题讨论】:

  • Index 是什么?行号?
  • 是的,Index 是行号。目前从 0 运行到 4。

标签: c++ c++11 c++14 variadic-templates stdarray


【解决方案1】:

看起来你快到了。只依赖参数包扩展:

return std::array<std::array<unsigned, 2>, sizeof...(Indices)>
{
   getRow<Indices>()...
};

getRow&lt;Indices&gt;()... 行将扩展到:

getRow<0>(), getRow<1>(), ..... , getRow<sizeof...(Indices)-1>()

【讨论】:

    【解决方案2】:

    +1 用于 KyleKnoepfel 的解决方案,但我在我的 amd64 linux 中编译您的代码时遇到问题,因为“错误:没有用于调用 'generateTable' 的匹配函数”和“候选模板被忽略:替换失败:推断出的非类型模板参数与其对应的模板参数的类型不同('unsigned long' vs 'unsigned int')”

    问题是std::make_index_sequence&lt;kCount&gt;{} 生成了std::size_t 的序列。如果std::size_t定义为unsigned int,则一切顺利;如果(如在我的平台中)std::size_t 定义为 unsigned long,则以下声明无效

    template<unsigned... Indices>
    constexpr auto generateTable(std::index_sequence<Indices...>)
    

    建议:使用std::size_t 而不是unsigned;特别是

    template<std::size_t ... Indices>
    constexpr auto generateTable(std::index_sequence<Indices...>)
    

    顺便说一句,用{ val1, val2 }(只有一层大括号)初始化std::array,它在C++14中是完全合法的,但是(恕我直言)我认为最好使用旧的(C++11)语法双层大括号 ({ { val1, val2 } });这是为了向后兼容(如 Wum 所指出的)并避免某些编译器(如 clang++ 3.5)出现烦人的警告。所以我建议在数组声明/初始化中使用第二级大括号,所以

    return std::array<unsigned, 2> { { Index, Index * Index } };
    

    return std::array<std::array<unsigned, 2>, sizeof...(Indices)>
     { { getRow<Indices>() ... } };
    

    ps:对不起,我的英语不好。

    【讨论】:

    • 感谢您对std::size_t 的提示。我会记住这一点。能否请您解释一下第二级花括号的优点?
    • 赞成std::size_t 推荐,但为什么推荐双括号?
    • en.cppreference.com/w/cpp/container/array 告诉 C++11 需要双括号来保持 std::array 中的聚合初始化工作。所以这似乎是一个向后兼容的问题。
    • @CoffeeandCode(和 Wum) - 对不起:我的错;我曾经忘记 C++14 放宽了语法。但是,正如 Wum 所说,出于向后兼容性的原因(并避免对某些编译器发出恼人的警告,例如 clang 3.5),我认为最好使用旧语法。修改了答案以(尝试)明确这一点。
    猜你喜欢
    • 2023-03-10
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    相关资源
    最近更新 更多