2016-05-13 20 views
6

Si consideri il seguente codice:parziale specializzazione Template e ICC

template <class T, class U, class V> 
struct Foo { }; 

template <class T, class U> 
struct Foo<T, U, std::integral_constant<int, U::value>> { 
    static void print() 
    { 
    std::cerr << "instantiated"; 
    } 
}; 

template <class U> 
struct Foo<double, U, std::integral_constant<int, U::value>> { 
    static void print() 
    { 
    std::cerr << "instantiated special"; 
    } 
}; 

struct Bar { 
    static const int value = 0; 
}; 

int main(int argc, char ** argv) 
{ 
    using Baz = Foo<double, Bar, std::integral_constant<int, 0>>; 
    Baz::print(); 

    return 0; 
} 

Quando compilo questo con ICC 16.0.1, ricevo il seguente messaggio:

main.cpp(38): error: more than one partial specialization matches the template argument list of class "Foo<double, Bar, std::integral_constant<int, 0>>" 
      "Foo<T, U, std::integral_constant<int, U::value>>" 
      "Foo<double, U, std::integral_constant<int, U::value>>" 
    Baz::print(); 

Con clangore 3.7.1 e GCC 5.3.0 si compila (e viene stampato lo "speciale istanziato"). Si tratta di un bug in icc o il mio codice è errato? A me sembra chiaro che la seconda specializzazione è strettamente più specializzata della prima; è identico al primo diverso dal fatto che blocca il primo parametro del template.

Edit: dovrei aggiungere: se questo è un bug in icc, c'è una buona soluzione?

+0

Sicuramente mi sembra un errore in icc. – Cameron

+0

Puoi verificare se i suggerimenti nei [commenti seguenti] (https://stackoverflow.com/questions/37216212/partial-template-specialization-and-icc#comment61972971_37216503) risolvono il problema su ICC, per favore? Non è una soluzione completa per il tuo problema, ovviamente, solo un passo avanti nelle indagini. – bogdan

+0

Nel codice attuale, il numero intero proviene da un membro annidato di U, questo a sua volta ha causato problemi di clang, quindi il mio collega si è spostato dai parametri di tipo non di tipo a tipo. –

risposta

4

Sì, questo è un bug in ICC.


Entrambe le specializzazioni parziali corrispondono alla tua applicazione, in modo da andare nelle regole parziali modello ordinazione su due funzioni sintetizzati:

template <class T, class U> void f(Foo<T, U, std::integral_constant<int, U::value>); 
template <class U>   void f(Foo<double, U, std::integral_constant<int, U::value>); 

Le regole ordinamento parziale coinvolgono sintetizzare nuovi tipi per ogni argomento modello e tentano di fare deduzione con ogni sovraccarico rispetto al resto. Innanzitutto, tentiamo di dedurre U rispetto a Foo<_U1, _U2, std::integral_constant<int, _U2::value>>. Ciò non riesce, dal momento che _U1 non corrisponde a double. Quindi il primo sovraccarico non è almeno altrettanto specializzato del secondo. Successivamente, tentiamo di dedurre T e U contro Foo<double, _U3, std::integral_constant<int, _U3::value>>. Questo succede con T=double e U=_U3. Quindi il secondo sovraccarico è specializzato almeno quanto il primo.

Come risultato, il secondo sovraccarico è più specializzato rispetto al primo. C'è una parzializzazione parziale specialistica unica, che è quella che dovrebbe essere istanziata (ed è fatta da gcc e clang). L'incapacità di ICC di farlo è un bug.

+0

Ordinamento parziale e contesti non dedotti al lavoro di nuovo ... Sostituire 'U :: value' con un' int I 'dedotto molto probabilmente farà funzionare le cose come previsto. Sembra che il front-end EDG (molto probabilmente usato da ICC qui) sia d'accordo con MSVC e non rende né il sovraccarico almeno specializzato quanto l'altro a causa del contesto non dedotto. Preoccupante, ho testato un EDG non MSVC nella sua modalità '--strict' e fa ancora la stessa cosa. Sono 2 su 2 mentre i compilatori vanno. Semplicemente fantastico – bogdan

+0

@bogdan Perché ciò renderebbe impossibile la deduzione? – Barry

+0

Sono d'accordo sul fatto che non ha senso che la deduzione fallisca nel secondo passaggio della spiegazione. Stavo solo sottolineando che il contesto non dedotto è molto probabilmente la causa del problema (e sono molto sorpreso dal comportamento di EDG). Chiederò all'OP di controllare se la modifica di 'U :: value' a' 0' (o come suggerito sopra) risolve il problema su ICC. – bogdan

Problemi correlati