2016-05-13 19 views
6

Rozważmy następujący kod:Częściowa specjalizacja szablonu i 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; 
} 

Kiedy skompilować to z MTK 16.0.1, pojawia się następujący komunikat:

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

Z brzękiem i gcc 3.7.1 5.3.0 ta kompilacja (i "instancja specjalna" jest drukowana). Czy jest to błąd w Icc, czy mój kod jest niepoprawny? Wydaje mi się jasne, że druga specjalizacja jest ściśle wyspecjalizowana niż pierwsza; jest identyczny jak pierwszy, niż fakt, że blokuje pierwszy parametr szablonu.

Edit: Dodam: jeśli jest to błąd w MTK, czy istnieje dobry obejście?

+0

Sure wygląda jak błąd w Icc dla mnie. – Cameron

+0

można sprawdzić, czy sugestie w komentarzach poniżej [] (https://stackoverflow.com/questions/37216212/partial-template-specialization-and-icc#comment61972971_37216503) rozwiązać problem na MTK, proszę? Niezupełna poprawka dla twojego problemu, oczywiście, tylko krok naprzód w dochodzeniu. – bogdan

+0

W rzeczywistym kodzie, liczba całkowita pochodzi od zagnieżdżonego elementu U, co z kolei spowodowało problemy z klangami, więc mój kolega przesunął się z nie typu na typ parametrów szablonu. –

Odpowiedz

4

Tak, jest to błąd w ICC.


Oba częściowe specjalizacje dopasować swoją realizację, więc idź do częściowych reguł szablon zamawiania na dwóch syntetyzowanych funkcji:

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

cząstkowe zasady zamawiania polegają syntetyzowania nowych typów dla każdego argumentu szablonu i próbujących zrobić odliczenie z każdym przeciążeniem w stosunku do pozostałych. Najpierw próbujemy wywnioskować U przeciwko Foo<_U1, _U2, std::integral_constant<int, _U2::value>>. To się nie powiedzie, ponieważ _U1 nie pasuje do double. Zatem pierwsze przeciążenie nie jest tak wyspecjalizowane jak drugie. Następnie próbujemy wywnioskować T i U przeciwko Foo<double, _U3, std::integral_constant<int, _U3::value>>. Udaje się to z T=double i U=_U3. Więc drugie przeciążenie jest przynajmniej tak wyspecjalizowane jak pierwsze.

W rezultacie drugie przeciążenie jest bardziej wyspecjalizowane niż pierwsze. Istnieje unikalna najbardziej wyspecjalizowana częściowa partycjonowanie, która powinna być tworzona (i jest przez gcc i clang). Błąd ICC to błąd.

+0

Częściowe porządkowanie i niezrealizowane konteksty w pracy ponownie ... Zastąpienie 'U :: value' z dedukowanym' int I' najprawdopodobniej sprawi, że wszystko będzie działać zgodnie z oczekiwaniami. Wygląda na to, że front-end EDG (najprawdopodobniej używany tutaj przez ICC) zgadza się z MSVC i nie powoduje przeciążenia co najmniej tak wyspecjalizowanego jak inne z powodu niewydanego kontekstu. Niepokojąco przetestowałem edytor EDG bez MSVC w trybie '--strict' i nadal robi to samo. Jest 2 na 2, jak kompilatory go. Po prostu świetnie. – bogdan

+0

@bogdan Dlaczego spowodowałoby to, że odliczenie się nie udawało? – Barry

+0

Zgadzam się, że nie ma sensu, aby odliczenie zakończyło się niepowodzeniem na drugim etapie wyjaśnień. Po prostu wskazywałem, że nie wywnioskowany kontekst jest najprawdopodobniej przyczyną problemu (i jestem bardzo zaskoczony zachowaniem EDG). Poproszę OP o sprawdzenie, czy zmiana "U :: value" na "0" (lub jak sugerowano powyżej) rozwiązuje problem w ICC. – bogdan

Powiązane problemy