Чтобы гарантировать, что constexpr
функции оцениваются во время компиляции, вы должны заставить их быть, сделав их результат constexpr
. Например:
#include <array>
int
main()
{
constexpr std::array<int, 5> arr{1, 2, 3, 4, 5};
int i = arr[6]; // run time error
}
Однако:
#include <array>
int
main()
{
constexpr std::array<int, 5> arr{1, 2, 3, 4, 5};
constexpr int i = arr[6]; // compile time error
}
К сожалению, чтобы это действительно работало, std::array
должно соответствовать спецификации C++14, а не спецификации C++11. Поскольку спецификация C++11 не помечает const
перегрузку std::array::operator[]
с помощью constexpr
.
Так что в С++ 11 вам не повезло. В C++14 вы можете заставить его работать, но только если и array
, и результат вызова оператора индекса объявлены как constexpr
.
Пояснение
Спецификация С++ 11 для индексации массива гласит:
reference operator[](size_type n);
const_reference operator[](size_type n) const;
И спецификация С++ 14 для индексации массива гласит:
reference operator[](size_type n);
constexpr const_reference operator[](size_type n) const;
т.е. constexpr
был добавлен к перегрузке const
для C++14.
Обновить
И спецификация С++ 17 для индексации массива гласит:
constexpr reference operator[](size_type n);
constexpr const_reference operator[](size_type n) const;
Теперь цикл завершен. Вселенная может быть вычислена во время компиляции. ;-)
person
Howard Hinnant
schedule
19.12.2014
arr[n]
, потому что UB не вызывается до тех пор, пока выполнение не достигнет этой точки; например этот код может быть в функции, которая никогда не вызывается. - person M.M   schedule 19.12.2014arr[98]
, то UB может вернуться во времени к этапу компиляции. - person M.M   schedule 19.12.2014