C++11 added the constexpr keyword which can be added to functions to specify constant behavior.
C23 added what seems to be identical functionality in the form of the [[reproducible]] tag.
How are these two mechanisms different?
C++11 added the
constexpr
keyword which can be added to functions to specify constant behavior.C23 added what seems to be identical functionality in the form of the [[reproducible]] tag.
How are these two mechanisms different?
Generally speaking, the C++ (or C) constexpr
specifier is much stronger than the C [[reproducible]]
attribute, and the former has much more extensive semantics and stronger constraints. Moreover, constexpr
is part of program semantics, whereas [[reproducible]]
, as an attribute, serves as optional metadata that a compiler can use or not as it chooses. [[reproducible]]
can freely be removed without changing the validity or semantics of the program, provided that a function defined without [[reproducible]]
is not called from a scope in which its in-scope declaration carries that attribute.
Considering only facets that apply to both languages, here are some more details:
calls to constexpr
functions can appear in constant expressions, which implies that they can be evaluated at compile time. The former is not true of reproducible functions, and it is not necessary that it be possible to evaluate calls to reproducible functions at compile time.
C++ constexpr
functions have limits on their argument and return types, whereas C reproducible functions do not.
In some versions of C++, constexpr
functions have limits on the kind of statements that can appear in their definitions (goto
, labels, ...), whereas C reproducible functions do not.
In C++, the definition and all declarations of a function must agree about whether it is a constexpr
function. In C, a function defined with the reproducible
attribute can safely be redeclared without it, in any translation unit.
A C++ constexpr
function cannot write to non-local objects, and cannot read most non-local objects. A C [[reproducible]] function is not limited in which objects it may read. A reproducible function may write to non-local objects via pointers provided to it as arguments.
Every call to a C++ constexpr
function with the same arguments must produce the same return value (if any), whereas two calls to a reproducible function with the same arguments are required to produce the same return value only if the calls are performed one immediately after the other.
Overall, constexpr
and [[reproducible]]
have some general similarities, but they have very different significance, effects, and purpose. They are nowhere close to "identical". On the other hand, C23 also introduces constexpr
to C, with semantics for objects very similar to C++ constexpr
. In C, however, constexpr
can be applied only to objects, not to functions.