Преобразование кода в constexpr

Каковы общие советы по преобразованию кода в constexpr? Скажем, есть алгоритм некоторой геометрической трансформации (входной) геометрической фигуры. Ввод и вывод различаются по природе и размеру и нетривиально зависят друг от друга. В настоящее время он реализован как класс, который в настоящее время использует std::map и std::vector (без потери общности).

Как можно реорганизовать код, использующий динамическую память, чтобы получить код, который соответствует требованиям для константных выражений?

Я могу представить некоторую комбинацию constexpr-совместимых контейнеров и constexpr-совместимую реализацию "распределителя стека" ( для достаточно большого хранилища) на каждые value_type используемых контейнеров. Но есть проблема: таких контейнеров я не встречал. Но, может быть, есть другие способы?


person Tomilov Anatoliy    schedule 21.01.2016    source источник
comment
это слишком общее.   -  person David Haim    schedule 21.01.2016
comment
@DavidHaim Где место для таких общих вопросов? Я перемещаю вопрос в это место. Есть такое место?   -  person Tomilov Anatoliy    schedule 21.01.2016
comment
У вас есть что-то, что должно (или могло бы) быть выражением или значением времени компиляции? У вас есть функция, отвечающая всем требованиям для constexpr функции? Затем вы можете создать выражение, переменную или функцию constexpr. И это не повредит, если вы сделаете что-то constexpr, если это что-то действительно не является или не может быть константой времени компиляции, в этом случае это просто подразумевает const.   -  person Some programmer dude    schedule 21.01.2016
comment
@JoachimPileborg В настоящее время нет, но хочу. Я не использую reinterpret_cast, размещение new и прочие странности. Но я хочу написать constexpr код, который с точки зрения читателя похож на свой не constexpr аналог. Я хочу установить какое-то взаимное предубеждение.   -  person Tomilov Anatoliy    schedule 21.01.2016


Ответы (1)


Для большинства алгоритмов и служебных классов (std::bitset, std::array и т. Д.) В стандартной библиотеке вы можете просто добавить спецификатор constexpr везде и попытаться сохранить результат в переменной constexpr. Скорее всего, он будет успешно скомпилирован и запущен. См. Также этот вопрос и ответ.

От компиляции такого кода обычно останавливается одно из текущих языковых ограничений на выражения констант времени компиляции, например (полный список см. В 5.20 Постоянные выражения [expr.const])

  • распределение динамической памяти (например, внутри std::inplace_merge)
  • виртуальные функции (в <iostream>)
  • лямбда-выражения (предложены и приняты для стандартизации в < strong> N4487)
  • reinterpret_cast
  • goto (предложено, но отклонено для стандартизации в N4472)

Для каждого ограничения есть способы обойти его.

  • Альтернативой динамическому распределению памяти, поддерживаемому системой через _9 _ / _ 10_, является запись собственного пула памяти в большой глобальный массив constexpr.
  • Альтернативой виртуальным функциям является хранение массива указателей на функции (которые вызывают constexpr функции) и отправка их с помощью оператора switch.
  • Альтернативой лямбдам является написание собственных объектов функций с constexpr operator().
  • Альтернативой reinterpret_cast является использование constexpr вариантаunion под ним).
  • Альтернативой goto является написание более структурированного кода с использованием регулярных циклов и ветвлений.

Во всех случаях вы потеряете синтаксические тонкости, связанные с возможностью вызова _19 _ / _ 20_ или неявной динамической диспетчеризации. Вам придется вручную выделить / освободить память и вручную выбрать указатель функции.

Обратите внимание, что даже несмотря на то, что большие части стандартной библиотеки могут быть сделаны constexpr даже с текущим языком C ++ 14/17, в настоящее время это не так. Более того, разработчикам стандартных библиотек запрещается добавлять дополнительные constexpr функции (в отличие от того, что им разрешено предлагать более сильную noexcept поддержку).

Жалуйтесь своим поставщикам или комитету C ++, если считаете, что поддержка constexpr должна быть более или менее простой (как на языке, так и в стандартной библиотеке).

person TemplateRex    schedule 21.01.2016
comment
Альтернативой reinterpret_cast из необработанного хранилища является использование варианта constexpr (например, this). - person Tomilov Anatoliy; 21.01.2016