Reputation: 2553
#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);
}
Upvotes: 8
Views: 337
Reputation: 14714
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.
Upvotes: 1
Reputation: 65630
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.
Upvotes: 2