Это какое-то продолжение для этой темы и касается небольшой части. Как и в предыдущем разделе, рассмотрим, что наш компилятор имеет функции constexpr
для std::initializer_list
и std::array
. Теперь отпустите прямо к точке.
#include <array>
#include <initializer_list>
int main()
{
constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
constexpr int a0 = a[0];
constexpr int a1 = a[1];
constexpr int a2 = a[2];
constexpr std::initializer_list<int> b = { a0, a1, a2 };
return 0;
}
#include <array>
#include <initializer_list>
int main()
{
constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
constexpr std::initializer_list<int> b = { a[0], a[1], a[2] };
return 0;
}
Сбой этой ошибки:
error: 'const std::initializer_list<int>{((const int*)(&<anonymous>)), 3u}' is not a constant expression
Несмотря на то, что я прочитал несколько статей о constexpr
и постоянных выражениях, это поведение по-прежнему не имеет для меня никакого смысла. Почему первый пример считается допустимым постоянным выражением, а не вторым? Я бы приветствовал любое объяснение, чтобы после этого я мог спокойно отдохнуть.
ПРИМЕЧАНИЕ.. Я точно это уточню, Clang не сможет скомпилировать первый фрагмент, поскольку он не реализует дополнения библиотеки constexpr
, которые планируются для С++ 14. Я использовал GCC 4.7.
EDIT: Хорошо, вот большой пример, чтобы показать, что отклонено, а что нет:
#include <array>
#include <initializer_list>
constexpr int foo = 42;
constexpr int bar() { return foo; }
struct eggs { int a, b; };
int main()
{
constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
constexpr int a0 = a[0];
constexpr int a1 = a[1];
constexpr int a2 = a[2];
// From Xeo and Andy tests
constexpr std::array<int, 1> a = { bar() }; // OK
constexpr std::array<int, 3> b = {{ a[0], a[1], a[2] }}; // OK
std::initializer_list<int> b = { a[0], a[1], a[2] }; // OK
constexpr std::initializer_list<int> b = { a0, a1, a2 }; // OK
constexpr std::initializer_list<int> b = { foo }; // OK
constexpr std::initializer_list<int> c = { bar() }; // ERROR
constexpr std::initializer_list<int> b = { a[0], a[1], a[2] }; // ERROR
// From Matheus Izvekov and Daniel Krügler
constexpr eggs good = { 1, 2 }; // OK
constexpr std::initializer_list<eggs> bad = { { 1, 2 }, { 3, 4 } }; // ERROR
constexpr std::initializer_list<eggs> bad2 = { good, good }; // ERROR
return 0;
}