2016-05-13 25 views
6

Betrachten Sie den folgenden Code ein:Teil Vorlage Spezialisierung und 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; 
} 

Als ich das 16.0.1 mit icc kompilieren, erhalte ich die folgende Meldung:

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(); 

Mit Klirren 3.7.1 und gcc 5.3.0 dies kompiliert (und "instanziiert special" wird gedruckt). Ist das ein Fehler in ICC oder ist mein Code falsch? Für mich ist klar, dass die zweite Spezialisierung strikter spezialisiert ist als die erste; Es ist identisch mit dem ersten, außer dass es den ersten Template-Parameter sperrt.

Edit: Ich sollte hinzufügen: Wenn dies ein Fehler in ICC ist, gibt es eine gute Problemumgehung?

+0

Sure sieht aus wie ein Fehler in ICC zu mir. – Cameron

+0

Könnten Sie überprüfen, ob die Vorschläge in den [Kommentare unten] (https://stackoverflow.com/questions/37216212/partial-template-specialization-and-icc#comment61972971_37216503) das Problem auf ICC beheben, bitte? Nicht eine vollständige Lösung für Ihr Problem, natürlich, nur ein Schritt vorwärts in der Untersuchung. – bogdan

+0

In dem tatsächlichen Code stammt die Ganzzahl von einem verschachtelten Mitglied von U, das wiederum kling Probleme, so wechselte mein Kollege von Nicht-Typ zu Typ Vorlage Parameter. –

Antwort

4

Ja, das ist ein Fehler in ICC.


Beide Teil Spezialisierungen Ihre Implementierung übereinstimmen, so gehen in die Teilvorlage Ordnungsregeln auf zwei synthetisierten Funktionen:

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>); 

Die Teilordnungsregeln neue Typen für jede Vorlage Argument beinhalten die Synthese und versucht zu tun Abzug mit jeder Überladung gegen den Rest. Zuerst versuchen wir, U gegen Foo<_U1, _U2, std::integral_constant<int, _U2::value>> abzuleiten. Dies schlägt fehl, da _U1 nicht mit double übereinstimmt. Die erste Überladung ist also nicht mindestens so spezialisiert wie die zweite. Als nächstes versuchen wir, T und U gegen Foo<double, _U3, std::integral_constant<int, _U3::value>> abzuleiten. Dies gelingt mit T=double und U=_U3. Die zweite Überladung ist also mindestens so spezialisiert wie die erste.

Als Folge ist die zweite Überlastung spezialisierter als die erste. Es gibt eine einzigartige, am meisten spezialisierte partielle Partialisierung, die instanziiert werden sollte (und durch gcc und clang erfolgt). ICC's Fehler ist ein Fehler.

+0

Partielle Ordnung und nicht-abgeleitete Kontexte bei der Arbeit wieder ... Das Ersetzen von "U :: value" mit einem abgeleiteten "int I" wird wahrscheinlich die Dinge wie erwartet funktionieren lassen. Es sieht so aus, als ob das EDG-Front-End (höchstwahrscheinlich von der ICC hier verwendet) mit MSVC übereinstimmt und aufgrund des nicht-abgeleiteten Kontexts keine Überlastung erzeugt, die mindestens so spezialisiert ist wie die andere. Besorgniserregend habe ich eine nicht-MSVC-quirks-EDG im "strict" -Modus getestet und es tut immer noch das Gleiche. Es ist 2 auf 2 als Compiler gehen. Einfach toll. – bogdan

+0

@bogdan Warum würde der Abzug zum Scheitern bringen? – Barry

+0

Ich stimme zu, dass es keinen Sinn macht, dass der Abzug im zweiten Schritt Ihrer Erklärung scheitert. Ich habe nur darauf hingewiesen, dass der nicht-abgeleitete Kontext wahrscheinlich die Ursache des Problems ist (und ich bin sehr überrascht über das Verhalten von EDG). Ich werde das OP bitten, zu überprüfen, ob das Ändern von "U :: value" auf "0" (oder wie oben vorgeschlagen) das Problem bei der ICC behebt. – bogdan

Verwandte Themen