Проблема, которую решает это изменение, заключается в возможности использовать non -const
std::array
в функции constexpr
для вычисления некоторого результата. Напомним, что constexpr
функции не могут вызывать не constexpr
функции при оценке во время компиляции.
В качестве примера рассмотрим функцию, которая вычисляет сумму от i = 1 до N. И для аргумента Для этого рассмотрим действительно глупый способ сделать это (в реальной жизни существуют глупые примеры, но они более сложны): создайте массив, инициализированный {1, 2, 3, ...}
, а затем возвращающий сумму элементов array
.
// Compute sum from i = 1 to N
template <unsigned N>
unsigned
sum() noexcept
{
std::array<unsigned, N> a{};
unsigned u = 1;
for (auto i = a.begin(); i != a.end(); ++i, ++u)
*i = u;
u = 0;
for (auto const x : a)
u += x;
return u;
}
Это прекрасно работает и может быть названо так:
auto x = sum<5>(); // x == 15
Теперь кто-то говорит: эй, давайте вычислим это во время компиляции!
В C + +17 это так же просто, как наложение constexpr
на sum
и x
:
// Compute sum from i = 1 to N
template <unsigned N>
constexpr
unsigned
sum() noexcept
...
constexpr auto x = sum<5>(); // x == 15
Но в C ++ 14 это не компилируется:
test.cpp:24:20: error: constexpr variable 'x' must be initialized by a constant expression
constexpr auto x = sum<5>();
^ ~~~~~~~~
test.cpp:11:21: note: non-constexpr function 'begin' cannot be used in a constant expression
for (auto i = a.begin(); i != a.end(); ++i, ++u)
^
И причина, по которой он не компилируется, заключается в том, что array<T, N>::begin()
не является constexpr
функцией.