#include <iostream>
#include <string>
void foo(int& k) { std::cout << "int&\n"; }
void foo(int&& k) { std::cout << "int&&\n"; }
void foo(const int& k) { std::cout << "const int&\n"; }
void foo(const int&& k) { std::cout << "const int&&\n"; }
int main() {
static constexpr int k = 1;
foo(k);
foo(1);
}
The output is:
const int&
int&&
What exactly is a constexpr variable treated as?
The overload for foo
gives const int&
.
Edit: Moving on with constexpr being deduced as const T&
;
Why does a constexpr at class scope fail to be passed to a function taking universal reference?!
#include <type_traits>
template <typename T>
void goo(T&& k) {
static_assert(std::is_same<decltype(k), const int&>::value, "k is const int&");
}
class F {
static constexpr int k = 1;
public:
void kk2 () { goo(k); }
};
int main () {
F a;
a.kk2();
}
The above fails to compile giving error undefined reference to F::k
However the below passes:
#include <type_traits>
template <typename T>
void goo(T&& k) {
static_assert(std::is_same<decltype(k), const int&>::value, "k is const int&");
}
int main() {
static constexpr int k = 1;
goo(k);
}
Static specifies the lifetime of the variable. A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.
constexpr functions are implicitly inline , but not implicitly static .
constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.
constexpr stands for constant expression and is used to specify that a variable or function can be used in a constant expression, an expression that can be evaluated at compile time. The key point of constexpr is that it can be executed at compile time. Your code may have been executed before you run it.
N3337 [dcl.constexpr]/9:
Aconstexpr
specifier used in an object declaration declares the object asconst
. [...]
Since you declared k
as constexpr
, it is also declared as const
, so the const int&
is selected in overload resolution.
foo(1);
In this case a temporary variable with the value 1
is passed to the function foo
, hence non-const rvalue.
/*static*/ constexpr int k = 1;
foo(k);
Here a named const variable with the value 1
is passed to the function foo
, hence const lvalue. The static
keyword has no effect on a constexpr
variable at function scope.
What exactly is a constexpr variable treated as?
When used in an expression that is not a constant expression, a constexpr
variable is just a const
variable.
Why does a constexpr at class scope fail to be passed to a function taking universal reference?!
You are getting a linker error because you odr-used the variable without defining it. You need a definition of F::k
at namespace scope in exactly one translation unit, just like you did for static const
member variables in C++98.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With