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.

4
  • 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
    Commented Nov 4, 2014 at 18:12
  • 1
    @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. Commented Nov 4, 2014 at 18:14
  • 1
    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[].
    – Casey
    Commented Nov 4, 2014 at 18:27
  • Compiling in clang 3.4 with --std=c++1y 3.5 with --std=c++14 does indeed seem to work as I'd expect.
    – inetknght
    Commented Nov 4, 2014 at 18:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.