10
#include <iostream>
#include <array>

int main(int argc, char **argv) {
    constexpr const std::array<int, 2> arr {{ 0, 1 }};
    constexpr const int arr2[] = { 0, 1};

    static_assert(arr[0] == arr2[0], "asdf");
    static_assert(arr[1] == arr2[1], "asdfasdf");

    return 0;
}

When compiled with gcc 4.8.2 and 4.9.1 using g++ test.cpp --std=c++11, the compilation succeeds. When compiled with clang 3.4 and 3.5 using clang++ test.cpp --std=c++11 however, the compilation fails:

test.cpp:8:16: error: static_assert expression is not an integral constant expression
        static_assert(arr[0] == arr2[0], "asdf");
                      ^~~~~~~~~~~~~~~~~
test.cpp:8:16: note: non-constexpr function 'operator[]' cannot be used in a constant expression

So my question is, which compiler is "right" in the sense of being compliant with C++11? And, if clang is correct, then why is std::array's operator[] not constexpr capable? Isn't that rather one of the things that std::array was supposed to help resolve?

1 Answer 1

9

It looks like clang is correct, operator [] is not a constexpr in C++11 but is a constexpr in C++14

constexpr const_reference operator[]( size_type pos ) const; (since C++14)

so compiling with -std=c++14 should work though (see it live).

In the C++11 draft standard section 23.3.2.1 Class template array overview has the following for operator []:

reference operator[](size_type n);
const_reference operator[](size_type n) const;

while the C++14 draft standard has the following:

reference operator[](size_type n);
constexpr const_reference operator[](size_type n) const;
^^^^^^^^^

Update

Draft standard N3485 which came after C++11, contains fixes an enhancements to C++11. It contains a constexpr version of operator []. If this was part of a defect report then gcc would be correct and this seems plausible considering clang 3.6.0 also accepts the program in C++11 mode.

Update 2

I found the document that introduced the changes, N3470 and since I can not find any defect reports on this specific issue then this seems like an enhancement and therefore should not be part of C++11.

Sign up to request clarification or add additional context in comments.

4 Comments

In C++11, it became possible to declare array::operator[] const as constexpr, but the committee didn't get around to doing so until C++14. In C++14, it became possible to declare array::operator[] as constexpr...
@Casey I found the document that introduced the change into N3485, I added it to my answer. As far as I understand if it was considered a defect it should be allowed in C++11 mode but otherwise not. The document does not clarify that though.
I was mostly poking fun at the standard: library changes often lag behind core, because core likes to make changes at the last minute without giving library adequate time to react. I believe that the constexpr additions in N3470 are an enhancement, since the only defect report for array that involves constexpr is LWG DR 720, and it doesn't involve operator[].
Compiling in clang 3.4 with --std=c++1y 3.5 with --std=c++14 does indeed seem to work as I'd expect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.