constexpr的推断类型是什么?

时间:2016-10-21 12:22:44

标签: c++ c++11 templates overloading 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);
}

输出结果为:

const int&
int&&

constexpr变量到底是什么? foo的重载给出了const int&

编辑:继续将constexpr推断为const T&;

为什么类范围的constexpr无法传递给采用通用引用的函数?!

#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();
}

以上无法编译给出错误undefined reference to F::k 但是以下通过:

#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);
}

2 个答案:

答案 0 :(得分:2)

  

N3337 [dcl.constexpr]/9:对象声明中使用的constexpr说明符将对象声明为const。 [...]

由于您将k声明为constexpr,因此它也被声明为const,因此在重载决策中选择了const int&

答案 1 :(得分:1)

http://example.com/foo/?bar=16&oof=myp

在这种情况下,值为foo(1); 的临时变量将传递给函数1,因此为非const rvalue。

foo

这里一个值为/*static*/ constexpr int k = 1; foo(k); 的命名const变量被传递给函数1,因此是const lvalue。 foo关键字对函数范围内的static变量没有影响。

  

constexpr变量究竟是什么被视为?

在不是常量表达式的表达式中使用时,constexpr变量只是constexpr变量。

  

为什么类范围的constexpr无法传递给采用通用引用的函数?!

您收到链接器错误,因为您在不定义变量的情况下使用该变量。您需要在命名空间范围内仅在一个翻译单元中定义const,就像您在C ++ 98中对F::k成员变量所做的那样。