7

Ich spielte ein wenig mit dem Index-Trick, um zu sehen, wohin ich gehen könnte, und stieß auf einen seltsamen Fehler ... Zuerst die einfachen, nicht so alten Indizes:Unerwartete nicht konstante std :: initializer_list

template<std::size_t...> 
struct indices {}; 

template<std::size_t N, std::size_t... Indices> 
struct make_indices: 
    make_indices<N-1, N-1, Indices...> 
{}; 

template<std::size_t... Indices> 
struct make_indices<0, Indices...>: 
    indices<Indices...> 
{}; 

habe ich eine Kompilierung-Array-Klasse aus einem std::initializer_list abgeleitet und es hatte Wende (davon ausgehen, dass N3471 Unterstützung von Ihrem Compiler ist. es ist in dem nächsten Standard sowieso sein wird). Hier ist sie:

template<typename T> 
struct array: 
    public std::initializer_list<T> 
{ 
    constexpr array(std::initializer_list<T> values): 
     std::initializer_list<T>(values) 
    {} 

    constexpr auto operator[](std::size_t n) 
     -> T 
    { 
     return this->begin()[n]; 
    } 
}; 

Also habe ich versucht, eine Funktion zu erstellen, die eine Kopie eines array kehrt nach 1 zu jedem seiner Mitglieder hinzugefügt haben:

template<typename T, std::size_t... I> 
auto constexpr add_one(const array<T>& a, indices<I...>) 
    -> const array<T> 
{ 
    return { (a[I]+1)... }; 
} 

Und mit dem Code zu beenden, hier ist mein Haupt:

int main() 
{ 
    constexpr array<int> a = { 1, 2, 3 }; 
    constexpr auto b = add_one(a, make_indices<a.size()>()); 

    return 0; 
} 

ich nicht, dass Code sowieso würde kompilieren dachte, aber ich bin ziemlich überrascht von der Fehlermeldung (hier ist die ideone Code):

In function 'int main()': 
error: 'const smath::array<int>{std::initializer_list<int>{((const int*)(& const int [3]{2, 3, 4})), 3u}}' is not a constant expression 

Also, könnte mir jemand erklären, was nicht genau genug für den Compiler im obigen Code ist?

EDIT: Follow-ups für diese Frage

+2

Ein * Klammer-oder-gleich * Initialisierer ist kein Ausdruck und kann als solcher nie ein konstanter Ausdruck sein, ist, was ich denke, ist das Problem hier. – Xeo

+0

In der Tat, Clang 3.2 lehnt sogar die Initialisierung von 'a' –

+0

@AndyProwl Ich weiß, Clang unterstützt N3471 nicht, deshalb :) – Morwenn

Antwort

0

Von: dem Mann selbst http://www.stroustrup.com/sac10-constexpr.pdf

Im Einzelnen: sein Rückgabetyp und die Arten von seine Parameter (falls vorhanden) sind Literal Typen (siehe x2.2). Zur Konkretheit gehören zu den wörtlichen Typen bool, int oder double; sein Körper ist eine zusammengesetzte Aussage des Formulars {return expr; } wo Ausdruck ist so, dass, wenn beliebige konstante Ausdrücke von geeigneten Typen für die Parameter in Ausdruck ersetzt werden, dann der resultierende Ausdruck ist ein konstanter Ausdruck wie in einleitenden Absatz von x2 definiert. Der Ausdruck Ausdruck wird als potentieller konstanter Ausdruck bezeichnet.