2016-01-21 3 views
4

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

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

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

+1

Это слишком общее. –

+0

@DavidHaim Где место для таких общих вопросов? Я перехожу к этому вопросу. Есть ли такое SO-место? – Orient

+0

У вас есть что-то, что * должно * (или может) быть выражением или значением времени компиляции? У вас есть функция, которая отвечает всем требованиям для функции '' constexpr' '(http://en.cppreference.com/w/cpp/language/constexpr)? Затем вы можете сделать выражение, переменную или функцию 'constexpr'. И это не повредит, если вы сделаете что-то 'constexpr', если что-то действительно не является или не может быть константой времени компиляции, в этом случае подразумевается' const'. –

ответ

5

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

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

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

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

  • Альтернативой системы поддерживается динамическое распределение памяти через new/delete - это написать свой собственный пул памяти в большом глобальном массиве constexpr.
  • Альтернативой виртуальным функциям является сохранение массива функций указателей (которые вызывают функции constexpr) и отправляют их через a switch.
  • Альтернативой lambdas является создание собственных функциональных объектов с a constexpr operator().
  • Альтернативой reinterpret_cast является использование constexpr variantunion под ним).
  • Альтернатива goto состоит в том, чтобы написать более структурированный код, используя обычные петли и ветки.

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

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

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

+1

Альтернативой 'reinterpret_cast' из необработанного хранилища является использование варианта' constexpr' (например [this] (https://github.com/eggs-cpp/variant)). – Orient