2017-02-14 2 views
3

Hier habe ich eine Klassenvorlage Foo definieren, spezialisieren seine Member-Funktion, und dann eine partielle Spezialisierung für diese Klasse liefern:etwas verwirrend über Klassenschablonen-Teil Spezialisierung & Klassen Mitglied Spezialisierung

// this is Foo_0 
template<typename T, typename S> 
class Foo { 
public: 
    void operator()() { 
     std::cout << "Foo_0\n"; 
    } 
    template<typename R> 
    void bar(R) { 
     std::cout << "I'm from Foo_0\n"; 
    } 
}; 
template<> 
template<> 
void Foo<double, int>::bar(double) { 
    std::cout << "Now I'm specialized!\n"; 
} 

// this is Foo_1 
template<typename T> 
class Foo<T, int> { 
public: 
    void operator()() { 
     std::cout << "Foo_1\n"; 
    } 
}; 

Und ich instanziiert Foo auf VS2015 wie folgt aus:

Überraschenderweise f() prints "Foo_0", die die Teilfachschablone foo_1 Einrichtung nicht gewählt. Was noch seltsamer ist, wenn ich die Spezialisierung von Foo :: bar (double) kommentiere, f() druckt "Foo_1"!

Dann ist dieses Ich teste:

Foo<int, int> f; 
f(); 

Diesmal f() auch prints "foo_1", wird die Klasse Spezialisierung angewendet.

So scheint es, dass die Spezialisierung von member bar() die Anwendung der partiellen Spezialisierung der Klassenvorlage beeinflussen. Ist das wahr? Warum funktioniert das so?

+0

Versuchen Sie, die explizite Funktionsvorlagenspezialisierung unterhalb der partiellen Klassenvorlagenspezialisierung zu verschieben. –

+0

@Kerrek SB Wenn ich es verschiebe, beschwert sich der Compiler, dass "Klasse Foo nicht Mitglied Bar" hat, scheint es, dass bar (double) als Mitglied von Foo_1 betrachtet wird. – Dardai

+1

gcc gelingt es, das Problem zu diagnostizieren (im Gegensatz zu Klängen) [Demo] (http://coliru.stacked-crooked.com/a/ed9bb1a4e9682621). ('Fehler: Teilspezialisierung von 'Klasse Foo ' nach Instanziierung von 'Klasse Foo ' [-fpermissive]') – Jarod42

Antwort

3

Die explizite Spezialisierung von Foo<double, int>::bar

template<> 
template<> 
void Foo<double, int>::bar(double) { 
    std::cout << "Now I'm specialized!\n"; 
} 

führt ein implizites Instanziierung Foo<double, int>. Dies ist eine bessere Übereinstimmung als die teilweise spezialisierte Foo<T, int>, so dass Sie Foo_0 anstelle von Foo_1 erhalten, es sei denn, Sie kommentieren die Spezialisierung bar.

Was könnten Sie tun, ist bar(double) in die allgemeine Klasse Vorlage Foo<T, S> als reguläres überladene Memberfunktion

template<class T, class S> 
class Foo { 
    // as before 

    void bar(double) { 
     std::cout << "Now I'm overloaded!\n"; 
    } 
}; 

Jetzt bewegen werden Sie Foo_1, live example bekommen. Beachten Sie, dass Sie Foo<double, int>::bar(double) nicht mehr aufrufen können. Wenn Sie das möchten, müssen Sie auch ein bar Mitglied der Teilspezialisierung Foo<T, int> hinzufügen.

+1

Danke, es ist sehr hilfreich – Dardai