Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty std::array<T, 0> doesn't have constexpr begin()?

Tags:

c++

The following code doesn't compile with clang and libc++: https://godbolt.org/z/rDL-_K

#include <array>
int main() {
    static constexpr std::array<int, 0> xs{};
    constexpr auto i = xs.begin();  // non-constexpr function 'begin' cannot be used in a constant expression

    return 0;
}

But if you change the 0 to a 1, it compiles.

Is this a bug in libc++ or is there a good reason for it? How could I work around this if I have generic constexpr code that uses begin/end?

(I've seen this question, but my example intentionally uses static to avoid this problem.)

like image 836
jtbandes Avatar asked Feb 29 '20 06:02

jtbandes


People also ask

How to declare a constexpr in c++?

A reference may be declared as constexpr when both these conditions are met: The referenced object is initialized by a constant expression, and any implicit conversions invoked during initialization are also constant expressions. All declarations of a constexpr variable or function must have the constexpr specifier.

Where to define constexpr?

constexpr stands for constant expression and is used to specify that a variable or function can be used in a constant expression, an expression that can be evaluated at compile time. The key point of constexpr is that it can be executed at compile time.

What is static constexpr in c++?

Static specifies the lifetime of the variable. A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.

Is constexpr inline?

The constexpr keyword implies inline. Performing computations at compiletime can have many advantages over doing them at runtime. Firstly it can increase runtime performance, as computations that would be done at runtime are already executed at compiletime.


1 Answers

I believe this is a bug in libc++ which was introduced in: https://reviews.llvm.org/D41223

In particular, the _LIBCPP_CONSTEXPR_AFTER_CXX14 is missing on begin(), end(), etc.

It seems to work in libstdc++: https://godbolt.org/z/xmfdot

The bug has been reported at https://bugs.llvm.org/show_bug.cgi?id=40124 but it sounds like it may not be fixed due to difficulties obtaining a constexpr pointer to an object when one has not been constructed.

like image 54
jtbandes Avatar answered Oct 25 '22 00:10

jtbandes