В чем разница между constexpr в C++11 и [[reproducible]] в C23?
В C++11 добавлено ключевое слово constexpr, которое можно добавлять к функциям для указания постоянного поведения.
C23 добавил, казалось бы, идентичную функциональность в виде тега [[reproducible]].
Чем отличаются эти два механизма?
3 ответа
Функция считается функцией, если она не оказывает заметного влияния на состояние программы, кроме возвращаемого значения, и если повторные вызовы в контексте одного и того же состояния программы будут возвращать одно и то же значение.
Стереотипная функция – это
требует, чтобы функция была неэффективной и идемпотентной, если эти термины имеют определенное значение в стандарте.
Это отличается от C++, который декорирует функцию, которая может быть вызвана в постоянном выражении и, следовательно, во время трансляции несколькими способами...
Первый,
Во-вторых, не требуется, чтобы вызов константного выражения функции constexpr не имел эффекта (по крайней мере, начиная с C++14) или чтобы она была идемпотентной с учетом состояния программы (по крайней мере, начиная с C++23). Пример.
В C++11 (до C++14)
В C++11 добавлено ключевое слово, которое можно добавлять к функциям для указания постоянного поведения.
C23 добавил, казалось бы, идентичную функциональность в виде тега [[reproducible]].
Чем отличаются эти два механизма?
Вообще говоря, спецификатор C++ (или C) намного сильнее, чем атрибут C, и первый имеет гораздо более обширную семантику и более строгие ограничения. Более того, является частью семантики программы, тогда как , как атрибут, служит дополнительными метаданными, которые компилятор может использовать или нет по своему усмотрению. может быть свободно удалено без изменения достоверности или семантики программы, при условии, что функция, определенная без, не вызывается из области, в которой ее объявление в области видимости содержит этот атрибут.
Учитывая только аспекты, применимые к обоим языкам, вот еще некоторые подробности:
вызовы функций могут появляться в константных выражениях, а это означает, что они могут быть оценены во время компиляции. Первое не относится к воспроизводимым функциям, и нет необходимости оценивать вызовы воспроизводимых функций во время компиляции.
Функции C++ имеют ограничения на типы аргументов и возвращаемых значений, тогда как воспроизводимые функции C — нет.
В некоторых версиях C++ функции имеют ограничения на типы операторов, которые могут присутствовать в их определениях (
goto
, метки, ...), тогда как воспроизводимые функции C этого не делают.В C++ определение и все объявления функции должны согласовывать, является ли она функцией. В C функция, определенная с помощью
reproducible
Атрибут можно безопасно переобъявить без него в любой единице перевода.Функция C++ не может писать в нелокальные объекты и не может читать большинство нелокальных объектов. Функция AC [[воспроизводимая]] не ограничена объектами, которые она может читать. Воспроизводимая функция может записывать данные в нелокальные объекты с помощью указателей, предоставленных ей в качестве аргументов.
Каждый вызов функции C++ с одинаковыми аргументами должен возвращать одно и то же возвращаемое значение (если таковое имеется), тогда как два вызова воспроизводимой функции с одинаковыми аргументами должны возвращать одно и то же возвращаемое значение только в том случае, если вызовы выполняются сразу после другой.
В целом и[[reproducible]]
имеют некоторые общие сходства, но имеют совершенно разные значения, эффекты и цели. Они далеко не «идентичны». С другой стороны, C23 также знакомит с C, семантика объектов которого очень похожа на C++. Однако в Cconstexpr
может применяться только к объектам, а не к функциям.
Их несколько, но в основном они предназначены для оценки времени компиляции вызова функции (где это применимо), тогда как[[reproducible]]
и[[unsequenced]]
действуют скорее как ограничения на функцию, которые допускают более инвазивные методы оптимизации, чем было бы законно в противном случае.
На практике компилятор может относиться к некоторым их аспектам одинаково, ноconstexpr
более универсален в том, что он позволяет, и более мягок в том смысле, что его можно понизить, чтобы он мог действовать во время выполнения за пределами своих ограничений.
Взглянув на предложение openstd здесь: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2887.htm . Мы видим, что авторы эффективно продвигаются к стандартизации существующих атрибутов GCC.pure
иconst
. На этот вопрос __attribute__((const)) и __attribute__((pure)) в GNU C есть несколько ответов, которые более подробно объясняют их поведение и различия.