Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the deduced type of a constexpr?

#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);
}
like image 487
themagicalyang Avatar asked Oct 21 '16 12:10

themagicalyang


People also ask

What is a static constexpr?

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.

Is constexpr implicitly static?

constexpr functions are implicitly inline , but not implicitly static .

What is a constexpr?

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.

What is a constexpr variable?

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.


2 Answers

N3337 [dcl.constexpr]/9: A constexpr specifier used in an object declaration declares the object as const. [...]

Since you declared k as constexpr, it is also declared as const, so the const int& is selected in overload resolution.

like image 147
TartanLlama Avatar answered Sep 27 '22 20:09

TartanLlama


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.

like image 43
Oktalist Avatar answered Sep 27 '22 19:09

Oktalist