Does constexpr imply inline?
Yes ([dcl.constexpr], §7.1.5/2 in the C++11 standard): "constexpr functions and constexpr constructors are implicitly inline (7.1.2)."
Note, however, that the inline
specifier really has very little (if any) effect upon whether a compiler is likely to expand a function inline or not. It does, however, affect the one definition rule, and from that perspective, the compiler is required to follow the same rules for a constexpr
function as an inline
function.
I should also add that regardless of constexpr
implying inline
, the rules for constexpr
functions in C++11 required them to be simple enough that they were often good candidates for inline expansion (the primary exception being those that are recursive). Since then, however, the rules have gotten progressively looser, so constexpr
can be applied to substantially larger, more complex functions.
Are all constexpr variable implicitly inline?
Are all constexpr variable implicitly inline?
No. Only constexpr functions and constexpr static data members are implicitly inline ([dcl.constexpr]/1).
Also, how does that affect the linkage of my variable bar?
A constexpr variable is const
([dcl.constexpr]/9). A non-inline const
variable that is not explicitly declared extern
has internal linkage ([basic.link]/3).
Replacing constants: when to use static constexpr and inline constexpr?
In C++17, the proper way to replace those old idioms (e.g. #define
) in headers in namespace scope is to use constexpr inline
variables -- and not static
(which is implied: they already have internal linkage).
While typically you won't encounter ODR issues (because integer compile-time constants such as those you describe are rarely ODR-used and there is a provision for their typical usage within inline
functions), it is best to mark them as inline
now that we have the feature in the language and avoid all problems.
See Should `const` and `constexpr` variables in headers be `inline` to prevent ODR violations? for the technical details about it.
What is the difference between inline and constexpr captureless lambda in a header?
If I understand correctly,
constexpr
imply inline, and lambdas areconstexpr
by default.
The first part is true, but not for this case. From [dcl.constexpr]/1:
A function or static data member declared with the
constexpr
orconsteval
specifier is implicitly an inline function or variable ([dcl.inline]).
In our case, we don't have either a function or a static data member, so it's not implicitly inline. You'd have to explicitly mark it as such.
The second part isn't quite right. From [expr.prim.lambda.closure]/4:
The function call operator or any given operator template specialization is a constexpr function if either the corresponding lambda-expression's parameter-declaration-clause is followed by
constexpr
orconsteval
, or it satisfies the requirements for a constexpr function ([dcl.constexpr]).
The call operator is constexpr
by default, but the lambda itself is not. Which for a capture-less lambda is basically fine, you can still use the call operator - as demonstrated in the example for this section:
auto ID = [](auto a) { return a; };
static_assert(ID(3) == 3); // OK
In short, if you're declaring this lambda in the header, you definitely need the inline
keyword and it doesn't hurt to just slap on the constexpr
keyword either.
inline constexpr have external linkage?
There seems to be a little bit of confusion about what "linkage" and "inline" actually means. They are independent (orthogonal) properties of a variable, but nevertheless coupled together.
To inline a variable one declares it inline
. Declaring a constexpr
variable at namescope does not imply inline
[1]. To declare a variable to have internal linkage one declares it static
or more preferrable puts it into an anonymous namespace [2],[3]. For const
and constexpr
(which implies const
) variables there is a special rule, which gives them internal linkage as long as they are non-inline [4].
Because constexpr
variables require an immediate definition [5], you typically want them to be be inline
which allows multiple (equivalent) definitions in multiple translation units:
\\ c.hpp
inline constexpr int c = 0; // define it in header
\\ a.cpp
#include "c.hpp" // c is defined in a.cpp
int a = c; // use it
\\ b.cpp
#include "c.hpp" // c is re-defined in b.cpp
int b = c; // use it
The linkage of c
in that example above is external, because the special rule for const
variables only applies to non-inline variables.
Note that when ommiting the inline
specifier in the example makes each source file get an independent non-inline definition of c
with internal linkage. It will still compile but you have to be careful to not use c
in any inline
functions [6].
You can put inline constexpr
variables into an anonymous namespace or declare it static
to make its linkage internal. If we changed the example above into
\\ c.hpp
namespace {
inline constexpr int c = 0;
};
\\ a.cpp
...
the effects would be almost the same as if ommitin the inline in the original example. Each translation unit gets its own version of the (now inline
d) variable and you have to make sure that you don't use c
in an inline
function.
inline vs. constexpr?
Asserting that something can be computed at compile-time is a pretty strong kind of optimization.
Inlining merely removes a function call, by copy/pasting the function body into the call site. The function body still has to be executed, you just save the overhead of a function call.
But if you make the same code be evaluated at compile-time, it is free at runtime.
But neither inline
nor constexpr
are primarily about optimization. inline
's main purpose is to suppress the one-definition-rule, so that functions can be defined in headers (which is useful for templates, and incidentally, also makes the inlining optimization easier)
And constexpr
is there because it is useful in metaprogramming, and incidentally, it may help the compiler better optimize the code, by moving more computations to compile-time.
What's the difference between static constexpr and static inline variables in C++17?
You don't have to specify an initializer for mySecondVar
at the point of declaration. Nor is the initializer required to be constexpr
itself.
This means that if we attempt to define myFirstVar
like this:
class MyClass {
static constexpr int myFirstVar;
};
int MyClass::myFirstVar = 1;
Or like this:
#include <cstdlib>
class MyClass {
static constexpr int myFirstVar = rand();
};
It's ill-formed either way. constexpr
semantics demand it and for a good reason.
The inline
specifier approach allows us to include a static variable definition in the header itself, without the initializer being constexpr
; or if the initializer is fairly complex it doesn't have to be in the class definition itself.
So this is a perfectly valid header in C++17:
#include <cstdlib>
class MyClass {
static const int mySecondVar;
};
inline const int MyClass::mySecondVar = rand();
The standard promises us that all translation units that include the header will see the same value for the variable, even though we won't know what it is until run-time.
It's mostly a library writers tool. Assume your library is header only. Then in the olden days, what were your options if you needed a static constant defined like this?
Well, you could have an object file shipped with your library. It will be compiled from a translation unit that contains just the constant definition. Now the library isn't header-only.
Or you could rely on inline functions instead. The inline variable effect can be achieved with the following:
class MyClass {
static inline int mySecondVar();
};
inline int MyClass::mySecondVar() {
static const int value = rand();
return value;
}
But it's hidden behind a wall of syntax, and masks what is essentially a constant, with a function call operator.
Related Topics
How to Multicast with Ipv6 Udp Socket in C/C++ on Linux
Deploying Qt Applications in Linux Properly
How to Create a Game Loop with Xlib
How to Access a Text File While Debugging with Eclipse Cdt
How to Measure CPU Time of a Specific Set of Threads
How to Avoid Multiple Definition Linking Error
Why Do You Use Std::Move When You Have && in C++11
Detecting CPU Architecture Compile-Time
How Std::Bind Works with Member Functions
Passing a Std::Array of Unknown Size to a Function
How to Make Visual Studio's Build Be Very Verbose
C++ Modules - Why Were They Removed from C++0X? Will They Be Back Later On
Writing Universal Memoization Function in C++11
Remove C and C++ Comments Using Python
Is It Still Safe to Delete Nullptr in C++0X
Is a Pointer with the Right Address and Type Still Always a Valid Pointer Since C++17