Построение массива const из constexpr

Предположим, у меня есть следующий закрытый constexpr в классе:

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

Затем я хочу построить массив статических констант из этих значений для целых чисел до 255 в том же разделе того же класса, используя вышеуказанный constexpr:

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

Я бы хотел, чтобы массив создавался во время компиляции, а не во время выполнения, если это возможно. Я думаю, что первая проблема заключается в том, что использование выражений типа std::pow в constexpr недопустимо в соответствии с ISO C++ (хотя возможно и разрешено arm-gcc?), Так как оно может возвращать ошибку домена. Фактическое выражение, которое я хочу использовать, является довольно сложной функцией, включающей std::exp.

Обратите внимание, что у меня не так много доступной библиотеки std, так как я собираю небольшой микропроцессор Cortex M4.

Есть ли более подходящий способ сделать это, скажем, с помощью макросов препроцессора? Я бы очень хотел избежать использования чего-то вроде внешнего скрипта Python для вычисления таблицы каждый раз, когда она должна быть изменена во время разработки, а затем вставлять ее.

2 ответа

Как насчет этого?

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), и, возможно, этот экземпляр шаблона займет слишком много памяти. Но, по крайней мере, это где-то работает.

Проблема, как вы говорите, заключается в том, что стандартные функции библиотеки C обычно не помечены constexpr,

Лучший обходной путь здесь, если вам нужно использовать std::exp, это написать свою собственную реализацию, которая может быть запущена во время компиляции. Если это должно быть сделано во время компиляции, то оптимизация, вероятно, не нужна, она должна быть точной и умеренно эффективной.

Кто-то задал вопрос о том, как это сделать здесь давным-давно. Вы можете использовать идею оттуда и переписать как constexpr функция в C++11, хотя вам придется реорганизовать ее, чтобы избежать цикла for. В C++14 потребуется меньше рефакторинга.

Вы также можете попробовать сделать это строго через шаблоны, но это будет более болезненным, и double не может быть параметром шаблона, поэтому будет сложнее.

Другие вопросы по тегам