简体   繁体   English

constexpr是一个std :: array的开头

[英]constexpr begin of a std::array

I am having trouble understanding why both gcc-8.2.0 and clang-7.0.0 reject the following code (live code here ): 我无法理解为什么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;
}

with the error 有错误

error: '(std::array<int, 3>::const_pointer)(& v.std::array<int,3>::_M_elems)' 
is not a constant expression (constexpr auto b = v.begin();)

According to en.cppreference.com , the begin() member function is declared constexpr . 根据en.cppreference.combegin()成员函数声明为constexpr Is this a compiler bug? 这是编译器错误吗?

So let's sidestep std::array to make this a bit easier: 所以让我们回避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

Why is b an error but global_b is okay? 为什么b是错误但global_b是可以的? Likewise, why would b become okay if we declared v to be static constexpr ? 同样,如果我们声明vstatic constexpr ,为什么b会变好? The problem is fundamentally about pointers. 问题基本上与指针有关。 In order to have a constant expression that's a pointer, it has to point to one, known, constant thing, always. 为了得到一个指针的常量表达式,它必须始终指向一个已知的常量事物。 That doesn't really work for local variables without static storage duration, since they have fundamentally mutable address. 对于没有静态存储持续时间的局部变量,这实际上不起作用,因为它们具有根本可变的地址。 But for function-local statics or globals, they do have one constant address, so you can take a constant pointer to them. 但对于函数局部静态或全局变量,它们确实有一个常量地址,因此可以对它们采用常量指针。


In standardese, from [expr.const]/6 : 在标准中,来自[expr.const] / 6

A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints: 常量表达式是glvalue核心常量表达式,它指的是一个实体,它是常量表达式的允许结果(如下所定义),或者是一个prvalue核心常量表达式,其值满足以下约束:

  • if the value is an object of class type, [...] 如果值是类类型的对象,[...]
  • if the value is of pointer type, it contains the address of an object with static storage duration , the address past the end of such an object ([expr.add]), the address of a function, or a null pointer value, and 如果值是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象末尾的地址([expr.add]),函数的地址或空指针值,以及
  • [...] [...]

b is none of those things in the second bullet, so this fails. b不是第二个子弹中的那些东西,所以这个失败了。 But global_b satisfies the bolded condition - as would b if v were declared static . 但是global_b满足粗体条件 - 如果v被声明为staticb

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

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