lin*_*ver 28 c++ constexpr c++17
我无法理解为什么gcc-8.2.0和clang-7.0.0都拒绝以下代码(这里的实时代码):
#include <array>
int main() {
constexpr std::array<int,3> v{1,2,3};
constexpr auto b = v.begin(); // error: not a constexpr
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有错误
error: '(std::array<int, 3>::const_pointer)(& v.std::array<int,3>::_M_elems)'
is not a constant expression (constexpr auto b = v.begin();)
Run Code Online (Sandbox Code Playgroud)
根据en.cppreference.com,begin()声明了成员函数constexpr.这是编译器错误吗?
Bar*_*rry 48
所以让我们回避std::array一下,让这更容易:
template <typename T, size_t N>
struct array {
T elems[N];
constexpr T const* begin() const { return elems; }
};
void foo() {
constexpr array<int,3> v{{1, 2, 3}};
constexpr auto b = v.begin(); // error
}
constexpr array<int, 3> global_v{{1, 2, 3}};
constexpr auto global_b = global_v.begin(); // ok
Run Code Online (Sandbox Code Playgroud)
为什么是b错误但是global_b没问题?同样,为什么b如果我们宣布成为好v是static constexpr?问题基本上与指针有关.为了得到一个指针的常量表达式,它必须始终指向一个已知的常量事物.对于没有静态存储持续时间的局部变量,这实际上不起作用,因为它们具有根本可变的地址.但是对于函数局部静态或全局变量,它们确实有一个常量地址,因此你可以对它们采用常量指针.
在标准中,来自[expr.const]/6:
甲常量表达式可以是一个glvalue芯常量表达式指的是一个常量表达式的结果允许的实体(如下面所定义),或一个prvalue芯常数表达式,其值满足以下约束条件:
- 如果值是类类型的对象,[...]
- 如果值是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象末尾的地址([expr.add]),函数的地址或空指针值,以及
- [...]
b在第二个子弹中没有这些东西,所以这失败了.但global_b满足粗体条件-正如b如果v被宣布static.