用constexpr构造const数组

时间:2016-03-20 18:40:47

标签: c++ c++11 arm constexpr lookup-tables

假设为了参数我在类中有以下私有constexpr:

static constexpr uint16_t square_it(uint16_t x)
{
    return std::pow(x, 2);
}

然后我想使用上面的constexpr在同一个类的同一部分中为最多255个整数构造这些值的静态常量数组:

static const uint16_t array_of_squares[256] =
{
    //something
};

我希望在编译时构造数组,如果可能的话,不要在运行时构建。我认为第一个问题是在constexpr中使用像std :: pow这样的表达式是无效的ISO C ++(尽管arm-gcc可能允许?),因为它可以返回域错误。我想要使​​用的实际表达式是一个涉及std :: exp。

的有点复杂的函数

请注意,由于我正在为一个小型微处理器Cortex M4进行编译,因此我没有太多可用的std库。

有没有更合适的方法来执行此操作,比如使用预处理器宏?我非常希望避免使用像外部Python脚本这样的东西来计算每次在开发过程中需要修改表格,然后粘贴它。

2 个答案:

答案 0 :(得分:1)

正如您所说,问题是C标准库函数通常没有标记为constexpr

如果您需要使用std::exp,这里最好的解决方法是编写您自己的可以在编译时运行的实现。如果它是在编译时完成的,那么可能没有必要对其进行优化,它只需要准确且适度有效。

很久以前有人问过如何做here的问题。您可以从那里重用该想法并在C ++ 11中重写为constexpr函数,尽管您必须重构它以避免for循环。在C ++ 14中,需要更少的重构。

您也可以尝试通过模板严格执行此操作,但这会更加痛苦,double不能成为模板参数,因此会更复杂。

答案 1 :(得分:1)

这样的事情怎么样?

constexpr uint16_t square_it(uint16_t v) { return v*v; }

template <size_t N, class = std::make_index_sequence<N>>
struct gen_table;

template <size_t N, size_t... Is>
struct gen_table<N, std::index_sequence<Is...>> {
    static const uint16_t values[N] = {square_it(Is)...};
};

constexpr auto&& array_of_squares = gen_table<256>::values;

我不知道微处理器是否支持这种操作。它可能在您的标准库中没有make_index_sequence(尽管您可以在SO上找到实现),也许该模板实例化会占用太多内存。但至少它可以在某个地方运作。