To jest pewien rodzaj obserwacji dla this topic i zajmuje się jej niewielką częścią. Podobnie jak w poprzednim temacie, załóżmy, że nasz kompilator ma funkcje constexpr
dla std::initializer_list
i std::array
. Teraz przejdźmy od razu do rzeczy.Zamieszanie o stałych wyrażeń
#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;
}
zawiesza się z tego błędu:
error: 'const std::initializer_list<int>{((const int*)(&<anonymous>)), 3u}' is not a constant expression
Chociaż czytałem jakieś papiery o constexpr
i stałych wyrażeń Tymczasem takie zachowanie wciąż nie ma dla mnie sensu. W jaki sposób pierwszy przykład jest uważany za poprawne wyrażenie stałe, a nie za drugi? Będę wdzięczny za wszelkie wyjaśnienia, aby później móc odpocząć w pokoju.
UWAGA: będę precyzyjny to od razu, Clang nie będzie w stanie opracować pierwszy fragment, ponieważ nie wdrożyć constexpr
uzupełnień bibliotecznych, które są zaplanowane na C++ 14. Użyłem GCC 4.7.
EDIT: Ok, tutaj jest wielki przykład, aby pokazać co jest odrzucane, a co nie:
#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;
}
Co powiecie na "GCC ma błąd"? :) (Nie mówiąc, że ma jedną, tylko możliwość.) Naprawdę, powinieneś być w stanie przetestować to bez dodatków "constexpr", pisząc własne analogi. A co z 'constexpr std :: array b = {{a [0], a [1], a [2]}};'? –
Xeo
Może [this] (http://ideone.com/56iP0Y) pomaga zawęzić problem –
@Xeo Cokolwiek robię z tablicą, wydaje się działać dobrze (w tym twój przykład i Andy z tylko 'std :: tablica' zamiast z 'std :: initializer_list'). Wygląda na to, że problem występuje tylko z 'std :: initializer_list' podczas kompilacji. Nie udało mi się go odtworzyć bez 'constexpr' lub' std :: array'. – Morwenn