使用可变参数模板的C++14编译时std::array

3
我希望使用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 中。每一行由一个具有2列的std::array组成。 我卡在了generateTable()中,在这里我需要以某种方式将我的 Indices 作为模板参数传递给getRow()
使用std::integer_sequence和模板参数包展开来实现这一点是否可行,还是我需要自己实现递归?
getRow()已简化-值类型实际上来自模板类型。Index * Index只是一个占位符。我需要知道如何使用参数包展开调用getRow()的方法。)

什么是 Index?行号吗? - Arunmu
是的,Index 是行号。目前从 0 到 4 运行。 - Wum
2个回答

9

看起来你已经快做完了。只需要依靠参数包展开:

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

“getRow<Indices>()…”这一行会扩展为:

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

4

赞成KyleKnoepfel的解决方案,但在我的amd64 linux上编译您的代码时出现问题,因为会报错“error: no matching function for call to 'generateTable'” 和 “candidate template ignored: substitution failure : deduced non-type template argument does not have the same type as the its corresponding template parameter ('unsigned long' vs 'unsigned int')”。

问题在于std::make_index_sequence<kCount>{} 生成了一个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...>)

顺便提一下,在C++14中,使用{ val1, val2 }(只有一层大括号)初始化std::array是完全合法的,但我认为最好使用旧的语法(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>() ... } };

p.s.: sorry for my bad English.


谢谢你提到 std::size_t 的提示。我会记住的。你能否解释一下第二层花括号的优点? - Wum
支持使用 std::size_t,但为什么要推荐双括号? - RamblingMad
http://en.cppreference.com/w/cpp/container/array 表明在 C++11 中需要双括号来使聚合初始化在 std::array 中正常工作。因此,这似乎是向后兼容的问题。 - Wum
@CoffeeandCode(和Wum)- 抱歉:是我的错;我曾经忘记了C++14放宽了语法。但是,正如Wum所说,出于向后兼容的原因(以及避免一些编译器(如clang 3.5)产生烦人的警告),我认为最好使用旧语法。修改了答案以(尝试)明确这一点。 - max66

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接