constexpr does not imply inline

Not too long ago a lot of my current projects code base (C++14 back then) was filled with “inline constexpr” specifiers. Then C++17 came along and brought us two things:

  • Inline variables
  • Implicit inline for constexpr

Or so I thought…

Studying assembly listenings I’ve noticed that quite a lot of my constexpr variabels (and constexpr variable templates) got duplicated for every translation unit. Finding that weird I rechecked the constexpr specifier page on cppreference where at the end of the first paragraph it says

A constexpr specifier used in a function or static member variable (since C++17) declaration implies inline.

Apparently constexpr does not always imply inline, at least not for variables declared in a header file. A quick test where I created a constexpr variable in a header and included it in two files confirmed that.

Without inline:

08001b10 l     O .rodata    00000004 constexpr_variable
00000000 l    df *ABS*	    00000000 main.cpp
08001b30 l     O .rodata    00000004 constexpr_variable
00000000 l    df *ABS*	    00000000 system_stm32f4xx.c

With inline:

08001b0c w     O .rodata    00000004 constexpr_variable

I can’t really comprehend why the committee decided that this would be a good idea. What’s the point of having multiple immutable things? Currently we have a keyword implicitly adding the meaning of another keyword in 2 out of 3 cases and producing overhead in the one case that’s missing. Also you’ll never notice when you forgot to add inline as constexpr definitions never violate ODR…