Путаница с константными выражениями

Это какое-то продолжениеЭта тема и имеет дело с небольшой частью этого. Как и в предыдущей теме, давайтеСчитаем, что наш компилятор имеетconstexpr функции дляstd::initializer_list а такжеstd::array, Теперь давайтепойдем прямо к делу.

Это работает:

#include 
#include 

int main()
{
    constexpr std::array a = {{ 1, 2, 3 }};
    constexpr int a0 = a[0];
    constexpr int a1 = a[1];
    constexpr int a2 = a[2];
    constexpr std::initializer_list b = { a0, a1, a2 };

    return 0;
}

Это не:

#include 
#include 

int main()
{
    constexpr std::array a = {{ 1, 2, 3 }};
    constexpr std::initializer_list b = { a[0], a[1], a[2] };

    return 0;
}

Вылетает с этой ошибкой:

error: 'const std::initializer_list{((const int*)(&)), 3u}' is not a constant expression

Хотя я читал некоторые статьи оconstexpr и постоянные выражения между тем, это поведение все еще не имеет никакого смысла для меня. Почему первый пример считается допустимым константным выражением, а не вторым? Я приветствовал бы любое объяснение, чтобы я мог покоиться с миром впоследствии.

НОТА: Я уточню это сразу, Clang не сможет скомпилировать первый фрагмент, поскольку он не реализуетconstexpr дополнения библиотеки, которые запланированы для C ++ 14. Я использовал GCC 4.7.

РЕДАКТИРОВАТЬ: Хорошо, вот большой пример, показывающий, что отклонено, а что нет:

#include 
#include 

constexpr int foo = 42;
constexpr int bar() { return foo; }
struct eggs { int a, b; };

int main()
{
    constexpr std::array 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 a = { bar() }; // OK
    constexpr std::array b = {{ a[0], a[1], a[2] }}; // OK
    std::initializer_list b = { a[0], a[1], a[2] }; // OK
    constexpr std::initializer_list b = { a0, a1, a2 }; // OK
    constexpr std::initializer_list b = { foo }; // OK
    constexpr std::initializer_list c = { bar() }; // ERROR
    constexpr std::initializer_list 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 bad = { { 1, 2 }, { 3, 4 } }; // ERROR
    constexpr std::initializer_list bad2 = { good, good }; // ERROR

    return 0;
}

Ответы на вопрос(2)

Ваш ответ на вопрос