Search code examples
c++cc++11syntaxc23

What is the difference between C++11's constexpr and C23's [[reproducible]]?


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?


Solution

  • 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.