繁体   English   中英

constexpr是一个std :: array的开头

[英]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.combegin()成员函数声明为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是可以的? 同样,如果我们声明vstatic constexpr ,为什么b会变好? 问题基本上与指针有关。 为了得到一个指针的常量表达式,它必须始终指向一个已知的常量事物。 对于没有静态存储持续时间的局部变量,这实际上不起作用,因为它们具有根本可变的地址。 但对于函数局部静态或全局变量,它们确实有一个常量地址,因此可以对它们采用常量指针。


在标准中,来自[expr.const] / 6

常量表达式是glvalue核心常量表达式,它指的是一个实体,它是常量表达式的允许结果(如下所定义),或者是一个prvalue核心常量表达式,其值满足以下约束:

  • 如果值是类类型的对象,[...]
  • 如果值是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象末尾的地址([expr.add]),函数的地址或空指针值,以及
  • [...]

b不是第二个子弹中的那些东西,所以这个失败了。 但是global_b满足粗体条件 - 如果v被声明为staticb

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM