问题
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;
}
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
. Is this a compiler bug?
回答1:
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
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.
In standardese, from [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:
- 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
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
.
来源:https://stackoverflow.com/questions/52972533/constexpr-begin-of-a-stdarray