Мутирование 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
.
Ответы
Ответ 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
.