constexpr std::array со static_assert

#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;
}

При компиляции с gcc 4.8.2 и 4.9.1 с использованием g++ test.cpp --std=c++11 компиляция завершается успешно. Однако при компиляции с clang 3.4 и 3.5 с использованием clang++ test.cpp --std=c++11 компиляция завершается ошибкой:

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

Итак, мой вопрос: какой компилятор «правильный» в смысле совместимости с С++ 11? И если clang правильно, то почему operator[] std::array не поддерживает constexpr? Разве это не одна из проблем, которую должен был решить std::array?


person inetknght    schedule 04.11.2014    source источник


Ответы (1)


Похоже, что clang верно, operator [] не является constexpr в C++11, но является constexpr в C++14

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

поэтому компиляция с -std=c++14 должна работать (посмотреть вживую).

В проекте стандарта C++11 раздел 23.3.2.1 Обзор массива шаблонов классов содержит следующее для operator []:

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

в то время как проект стандарта C++14 содержит следующее:

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

Обновить

Проект стандарта N3485, который появился после C ++11, содержит исправления и улучшения для C++11. Он содержит constexpr версию operator []. Если бы это было частью отчета о дефекте, то gcc был бы правильным, и это кажется правдоподобным, учитывая, что clang 3.6.0 также принимает программу в режиме C++11.

Обновление 2

Я нашел документ, в котором были представлены изменения, N3470 и поскольку я не могу найти никаких отчетов об ошибках по этой конкретной проблеме, это выглядит как улучшение и, следовательно, не должно быть частью C++11.

person Shafik Yaghmour    schedule 04.11.2014
comment
В C++11 стало возможным объявлять array::operator[] const как constexpr, но комитет не удосужился сделать это до C++14. В C++14 стало возможным объявлять array::operator[] как constexpr... - person Casey; 04.11.2014
comment
@Casey Я нашел документ, в котором были внесены изменения в N3485, и добавил его в свой ответ. Насколько я понимаю, если бы это считалось дефектом, это должно быть разрешено в режиме C++ 11, а в противном случае - нет. Однако в документе это не уточняется. - person Shafik Yaghmour; 04.11.2014
comment
В основном я подшучивал над стандартом: изменения в библиотеке часто отстают от ядра, потому что ядро ​​любит вносить изменения в последнюю минуту, не давая библиотеке достаточного времени для реакции. Я считаю, что дополнения constexpr в N3470 являются улучшением, поскольку единственный отчет о дефектах для array, который включает constexpr, это LWG DR 720 и не включает operator[]. - person Casey; 04.11.2014
comment
Компиляция в clang 3.4 с --std=c++1y 3.5 с --std=c++14 действительно работает, как я и ожидал. - person inetknght; 04.11.2014