constexpr std :: array的开头 [英] constexpr begin of a std::array

查看:100
本文介绍了constexpr 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆