Immediate functions in C++20

With C++11, compile-time programming has flourished in C++, and ever since, new standards kept on pushing new ideas to provide a richer and richer compile-time programming toolbelt. The upcoming release of the next standard, C++20, is no exception to this rule, and will provide its share of new features regarding this domain.

One of the accepted proposals for C++20 introduces immediate functions, that is, functions that are always evaluated at compile-time. This post will present these, by highlighting their differences with constexpr functions.

constexpr functions

With the introduction of constexpr, compile-time evaluation of functions transitioned from being an uncertain compiler optimization (depending on the code, the compiler, the optimization level, the current position of the stars, etc) to being a standardized language feature. Since this post is about functions, we will only discuss constexpr functions here.

As a language feature, constexpr functions provide more guarantees than regular functions that might or might not be candidates for constant propagation. For example, the compiler will verify that a function marked as constexpr can actually be reduced to a constant expression, and thus evaluated at compile-time. This has the useful consequence of making constexpr functions usable anywhere a constant expression is required.

However, it is not guaranteed that a constexpr function will always be evaluated at compile-time. This happens, for example, if it is passed arguments that are not constant expressions themselves (godbolt link) :

Furthermore, it is actually not even guaranteed that the compiler will “try its best” to evaluate it at compile-time (see this example).

To sum up, constexpr is only a marker used to express that the function can be used in a constant expression if needed.

Getting more specific with consteval

As we said above, the constexpr marker does not require the function to always be evaluated at compile-time. This can be useful in some contexts : for example, we want to be able to use STL algorithms at compile-time if needed, but also at runtime.

However, in some other contexts, we want to require compile-time evaluation for a function, and emit a compiler error if that is not possible. This was the topic of the P1073 proposal, which introduces the consteval specifier for functions. Its syntax is rather unsurprising:

It is also important to note that since they are evaluated at compile-time only, consteval functions will never be seen any further than the compilation step. No symbol will ever be emitted for them, thus their address cannot be taken, and they won’t show up in a debugger.

Why is this useful ?

You might be wondering why restricting the evaluation of certain functions to compile-time only is useful. After all, why forbid evaluation at runtime ? In order to understand the benefits of this feature, it is important to highlight its context as part of the language evolution.

  • The C++ committee has plans to make compile-time programming even more powerful in the upcoming years. There are lots of ideas and proposals out there, among which are the reflection and the metaclasses debates. For obvious reasons, these two features will live entirely in the compile-time world, thus they represent very important use cases for the consteval specifier.
  • Another place where consteval functions could prove useful would be taking over yet another use case of the preprocessor: function-like guaranteed compile-time calculations, which do not generate any code.
  • Furthermore, as we said above, constexpr functions can be evaluated at both compile-time and runtime. With the increasing number of library functions becoming constexpr and the ability to detect constant evaluation (with is_constant_evaluated), constexpr functions can be used efficiently both at runtime and compile-time. On the other hand, consteval functions should take over compile-time-only helpers.

As the consteval proposal was accepted into C++20, it should be part of the next batch of new features to appear in the C++ language, and will be ready to support other upcoming proposals for increasingly powerful compile-time programming.

Leave a Reply

Your email address will not be published. Required fields are marked *