Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to detect functions that could be marked `constexpr`?

Tags:

c++

constexpr

Given I want to improve my C++ code base. One step would be to mark functions as constexpr which fulfill the requirements of the used C++ standard. Is there a way to determine whether a function could be marked constexpr?

The only way I came up with is to add constexpr to a single instance, run the compiler, and check if it complains that it is not constexpr. Repeat until all instances are checked. This approach does not scale.

Related: Should we use constexpr everywhere we can?

like image 949
usr1234567 Avatar asked Oct 23 '25 21:10

usr1234567


2 Answers

In C++23, there are exactly two requirements for a constexpr function:

  • It is not a coroutine;
  • If it is a constructor or destructor, its class has no virtual base classes.

I would not be surprised if every single function in your code base satisfied this.

So you can mark every templated and inline function constexpr. Because constexpr functions are implicitly inline, you can't do this to extern functions.
This should mean every function definition in a header file can be constexpr.

(If you have compiler errors for constexpr functions that could never produce a constant expression, upgrade your compiler)

like image 166
Artyer Avatar answered Oct 25 '25 10:10

Artyer


As there are more and more relaxations for constexpr, it's easier to ask:

Is there a way to detect functions that shouldn't be constexpr?

The following functions should not be constexpr:

  1. functions with declaration/definition split between header/source
    • technically, you can make them constexpr, but they would be unusable in constant expressions without the definition being available
  2. member functions of classes which have no constexpr constructor
    • technically, they can be constexpr, but this constexpr would be misleading
  3. functions that never produce a constant expression (due to throw, goto, etc.)
    • even those can be marked constexpr since C++23, see P2448: Relaxing some constexpr restrictions
  4. functions that aren't constexpr-suitable even in C++23:
    • coroutines
    • constructors and destructors of classes with virtual base classes

Every other function (which in some code bases makes up the vast majority of functions) can be constexpr. You could even automate this process using something like a clang-tidy rule.

Note on C++20

It's more complicated in C++20 and older standards because there is the following rule:

For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression, or, for a constructor, an evaluated subexpression of the initialization full-expression of some constant-initialized object, the program is ill-formed, no diagnostic required.

- C++20 [dcl.constexpr] p6

This rule was dropped in the aforementioned proposal, but in C++20, it makes it harder to decide when to apply constexpr. Proving automatically whether there exists a set of arguments that produces a constant expression is not easy.

like image 33
Jan Schultke Avatar answered Oct 25 '25 10:10

Jan Schultke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!