Подтвердить что ты не робот

Мутирование int внутри функции constexpr

Почему я могу это сделать:

constexpr auto i_can() {
   int a = 8;
   a = 9;
   //...
}

Но я не могу этого сделать:

constexpr auto i_cannot() {
    std::array<int, 10> arr{};
    //I cannot
    arr[5] = 9;
}

Мои вопросы:

  • Если я могу мутировать int, почему я не могу мутировать int, который находится внутри массива?
  • Является ли это языковым ограничением (С++ 14) или стандартной проблемой спецификации библиотеки? reference std::array<T, N>::operator[](size_t) в настоящее время constexpr.
4b9b3361

Ответ 1

Это ограничение стандартной библиотеки, так как может изменять простой массив C в constexpr:

#include <iostream>

constexpr auto demo()
{
   int arr[10] = {};
   arr[5] = 9;
   return arr[5];
}

int main()
{
    static_assert(demo() == 9, "");
    std::cout << demo() << std::endl;
    return 0;
}   

DEMO

Выход

9

Если вы добавили constexpr в operator[] реализации array, вы также можете использовать этот оператор внутри constexpr.

DEMO

Ответ 2

Модификация объектов внутри функций constexpr была введена с С++ 14. Однако при модификации, например, скаляр по назначению прекрасен, модификация объекта класса через функцию-член все равно нуждается в том, чтобы функция-член была constexpr. К сожалению, как вы уже упоминали, текущая спецификация std::array не объявляет не const operator[] как constexpr.
Следовательно, в п. 7.1.5/5 ваше определение плохо сформировано:

Для функции без шаблона без функции constexpr [...], если нет значения аргумента существуют так, что вызов функции [...] может быть оцененным подвыражением выражения постоянной константы (5.20), [...], программа плохо сформирована; не требуется диагностика.

Вы можете временно использовать более современную реализацию, если хотите полный constexpr -ness. Например. Constainer::Array.