从 constexpr 构造 const 数组

Constructing const array out of constexpr

本文关键字:数组 const 构造 constexpr      更新时间:2023-10-16

假设为了论证,我在类中遵循私有 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::p ow 这样的表达式不是有效的 ISO C++(尽管 arm-gcc 可能允许?),因为它会返回域错误。我想使用的实际表达式是一个有点复杂的函数,涉及 std::exp。

请注意,我没有太多可用的标准库,因为我正在为小型微处理器 Cortex M4 进行编译。

有没有更合适的方法来做到这一点,比如使用预处理器宏?我非常希望避免每次在开发过程中需要修改表时都使用外部 Python 脚本之类的东西来计算表,然后将其粘贴到其中。

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

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

很久以前有人问了一个关于如何在这里做到这一点的问题。你可以从那里重用这个想法,并在 C++11 中重写为constexpr函数,尽管你必须重构它以避免 for 循环。在 C++14 中,需要的重构更少。

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

这样的事情怎么样?

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 上找到实现),并且该模板实例化可能会占用太多内存。但至少它在某个地方有效。