![](/img/trans.png)
[英]Empty std::array<T, 0> doesn't have constexpr begin()?
[英]constexpr begin of a std::array
我无法理解为什么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;
}
有错误
error: '(std::array<int, 3>::const_pointer)(& v.std::array<int,3>::_M_elems)'
is not a constant expression (constexpr auto b = v.begin();)
根据en.cppreference.com , begin()
成员函数声明为constexpr
。 这是编译器错误吗?
所以让我们回避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
为什么b
是错误但global_b
是可以的? 同样,如果我们声明v
是static constexpr
,为什么b
会变好? 问题基本上与指针有关。 为了得到一个指针的常量表达式,它必须始终指向一个已知的常量事物。 对于没有静态存储持续时间的局部变量,这实际上不起作用,因为它们具有根本可变的地址。 但对于函数局部静态或全局变量,它们确实有一个常量地址,因此可以对它们采用常量指针。
在标准中,来自[expr.const] / 6 :
常量表达式是glvalue核心常量表达式,它指的是一个实体,它是常量表达式的允许结果(如下所定义),或者是一个prvalue核心常量表达式,其值满足以下约束:
- 如果值是类类型的对象,[...]
- 如果值是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象末尾的地址([expr.add]),函数的地址或空指针值,以及
- [...]
b
不是第二个子弹中的那些东西,所以这个失败了。 但是global_b
满足粗体条件 - 如果v
被声明为static
则b
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.