constexpr std :: array的开头 [英] constexpr begin of a std::array
问题描述
我无法理解为什么gcc-8.2.0和clang-7.0.0都拒绝以下代码(实时代码这里):
I am having trouble understanding why both gcc-8.2.0 and clang-7.0.0 reject the following code (live code here):
#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
.这是编译器错误吗?
According to en.cppreference.com, the begin()
member function is declared constexpr
. Is this a compiler bug?
推荐答案
因此,让我们回避 std :: array
可以使此操作更简单:
So let's sidestep std::array
to make this a bit easier:
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
会变得可以呢?从根本上说,问题在于指针.为了拥有作为指针的常量表达式,它必须始终指向一个已知的常量对象.对于没有静态存储持续时间的局部变量,这实际上不起作用,因为它们具有根本上可变的地址.但是对于局部函数的静态变量或全局变量,它们确实具有一个常量地址,因此您可以使用指向它们的常量指针.
Why is b
an error but global_b
is okay? Likewise, why would b
become okay if we declared v
to be static constexpr
? 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.
以标准语言,来自 [expr.const]/6 :
常量表达式是glvalue核心常量表达式,它引用的是一个常量表达式(如以下定义)的允许结果的实体,或者是其值满足以下条件的prvalue核心常量表达式:受到以下限制:
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:
- 如果该值是类类型的对象,则[...]
- 如果该值是指针类型,则包含具有静态存储持续时间的对象的地址,该对象末尾的地址([expr.add]),一个函数或一个空指针值,以及
- [...]
- 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
- [...]
b
在第二个项目符号中都不是,所以失败了.但是 global_b
满足大胆的条件-如果将 v
声明为 static
,则 b
也会满足.
b
is none of those things in the second bullet, so this fails. But global_b
satisfies the bolded condition - as would b
if v
were declared static
.
这篇关于constexpr std :: array的开头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!