2013-04-15 19 views
7

Mi stavo un po 'trastullando con il trucco degli indici per vedere dove potevo andare e mi sono imbattuto in uno strano errore ... In primo luogo, i chiari indici non così vecchi:Inatteso non costante 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...> 
{}; 

ho creato una classe gamma di compilazione derivato da un std::initializer_list e aveva essa indicizzabili (scontato che N3471 è il supporto per il compilatore. sarà nel prossimo standard comunque). Eccolo:

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]; 
    } 
}; 

Così, ho cercato di creare una funzione che restituisce una copia di un array dopo l'aggiunta di 1 a ciascuno dei suoi membri:

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

e per finire con il codice, qui è il mio principale:

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

    return 0; 
} 

non pensavo che il codice avrebbe compilato in ogni caso, ma io sono molto sorpreso dal messaggio di errore (Ecco il ideone codice):

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 

Quindi, qualcuno potrebbe spiegarmi cosa non è esattamente abbastanza costante per il compilatore nel codice precedente?

EDIT: follow-up per questa domanda

+2

Un inizializzatore * brace-or-equal * non è un'espressione e in quanto tale non può mai essere un'espressione costante, è quello che ritengo sia il problema qui. – Xeo

+0

In effetti, Clang 3.2 rifiuta anche l'inizializzazione di 'a' –

+0

@AndyProwl Lo so, Clang non supporta N3471, ecco perché :) – Morwenn

risposta

0

Da: l'uomo stesso http://www.stroustrup.com/sac10-constexpr.pdf

In particolare: il suo tipo di ritorno, e i tipi di i suoi parametri (se presenti), sono letterali tipi (vedi x2.2). Per la concretezza, i tipi letterali includono bool, int o double; il suo corpo è una dichiarazione composta del modulo {return expr; } dove espr è tale che se le espressioni costanti arbitrarie dei tipi appropriati di vengono sostituite per i parametri in expr, allora l'espressione risultante è un'espressione costante definita nel paragrafo introduttivo di xdi x2. L'espressione expr è chiamata espressione potenziale potenziale .

Problemi correlati