2016-04-29 19 views
0

Ich habe eine Painter Vorlage Klasse mit paint() Vorlage Funktion. Ich verwende Tagging, um die Template-Funktion innerhalb der Template-Klasse zu spezialisieren. Ich habe die Definition der Template-Funktion paint() innerhalb Painter.h platziert und überladen Funktion innerhalb Painter.cpp.Mehrdeutige Vorlage Spezialisierung

Ich bekomme einen Compilerfehler, wenn ich paint() in Painter.cpp explizit instanziiere. Meine Anforderung ist, dass ich die Implementierung der überladenen Funktion paint(ColorTag<Color::RED>) in der Datei Painter.cpp brauche.

Quelldateien sind wie folgt:

Painter.h

#include <iostream> 

enum class Color { 
    RED = 0, 
    GREEN = 1, 
    BLUE = 2 
}; 

template<Color> 
struct ColorTag { 

}; 

template<typename T> 
class Painter { 
public: 

    template<Color MyColor> 
    void paint(ColorTag<MyColor>); 
    void paint(ColorTag<Color::RED>); 

}; 

template<typename T> 
template<Color MyColor> 
void Painter<T>::paint(ColorTag<MyColor>){ 
    std::cout << "General" << std::endl; 
} 

Painter.cpp

#include "Painter.h" 

template<typename T> 
void Painter<T>::paint(ColorTag<Color::RED>){ 
    std::cout << "RED" << std::endl; 
} 

template void Painter<int>::paint(ColorTag<Color::RED>); 

Main.cpp

#include "Painter.h" 

int main(){ 
    Painter<int> painter; 
    painter.paint(ColorTag<Color::RED>()); 
    return 0; 
} 

Zusammengestellt

g++ Main.cpp Painter.cpp -std=c++11 

ich mit Compiler-Fehler folgt, wenn ich

Painter.cpp:8:15: error: ambiguous template specialization ‘paint<>’ for ‘void Painter<int>::paint(ColorTag<(Color)0>)’ 
template void Painter<int>::paint(ColorTag<Color::RED>); 
      ^
Painter.cpp:4:6: note: candidates are: void Painter<T>::paint(ColorTag<(Color)0>) [with T = int] 
void Painter<T>::paint(ColorTag<Color::RED>){ 
    ^
In file included from Painter.cpp:1:0: 
Painter.h:20:10: note:     template<Color MyColor> void Painter<T>::paint(ColorTag<MyColor>) [with Color MyColor = MyColor; T = int] 
    void paint(ColorTag<MyColor>); 

ausdrücklich paint() in Painter.cpp instanziiert Was ich versucht

Zum einen I erstellt eine Vorlage functio n rief instantiatePaint() auf paint() Funktion zu rufen. Dann habe ich es in Painter.cpp Datei platziert und instanziiert. Das hat funktioniert. Aber diese Art von fühlt sich peinlich an.

template<typename T> 
template<Color MyColor> 
void Painter<T>::instantiatePaint(ColorTag<MyColor>){ 
    paint(ColorTag<MyColor>()); 
} 

template void Painter<int>::instantiatePaint(ColorTag<Color::RED>); 

Zweitens verschoben überladene Funktion Definition Painter.cpp-Painter.h. Dies funktioniert aber bricht meine Anforderung über die Funktion paint(ColorTag<Color::RED>) in Painter.cpp überlastet.

Gibt es bessere Methoden, um das Problem zu beheben oder was genau verursacht die Mehrdeutigkeit?

Antwort

-1
#include <iostream> 

enum Color { 
    RED = 0, 
    GREEN = 1, 
    BLUE = 2 
}; 

template<Color color = Color::RED> 
struct ColorTag 
{ 
    // your Implementation 
}; 

template<> 
struct ColorTag <Color::RED> 
{ 
    // your Implementation specific to Color::RED 
}; 

template<typename T> 
class Painter { 
public: 

    // template specialization can not apply on method level 
    // use class or struct 
    template<Color MyColor> 
    void paint(ColorTag<MyColor>); 
}; 

template<typename T> 
template<Color MyColor> 
void Painter<T>::paint(ColorTag<MyColor> colorTag) 
{ 
    std::cout << "General"<<std::endl; 
} 

adaequat auf Visual Studio 2012 nicht sicher Gcc

+1

bitte antworten Sie sehr sicher sind, dass dies 100% Arbeit „nicht sicher“ macht es brenzlig – piyushj

+0

, weil ich es nicht auf GCC geprüft habe ich irgendwo Doppel Vorlage lesen ist Compiler abhängig. – Jai

0

Was Sie wollen, ist eine explizite Spezialisierung mit T = int so korrekter Syntax ist:

template<> 
void Painter<int>::paint(ColorTag<Color::RED>); 

Mit dieser Syntax, die beide g ++ und Klirren kompiliere den Code. Live example

0

Warum können Sie die ganze Klasse nicht initialisieren, anstatt zu funktionieren?

template class Painter<int>; 
+0

Dies funktioniert, bis es bricht. Es gibt Fälle, in denen die gesamte Vorlagenklasse nicht explizit instanziiert werden kann. Nehmen wir an, wir haben zwei Strukturen, die 'int' ersetzen können. 'struct Box {statisch void foo() {std :: cout <<" foo ";}};' 'struct Würfel {static void bar() {std :: cout <<" Würfel ";}};'. Stellen Sie die Template-Funktion 'paint (ColorTag )' her, um 'T :: bar()' aufzurufen und eine spezielle Funktion, um 'T :: foo()' aufzurufen. Versuchen Sie nun, die gesamte Klasse mit 'Box' oder' Cube' zu ​​instanziieren. – Vivek

+0

Beachten Sie zunächst, dass in Ihrem Code 'paint (ColorTag )' keine Template-Spezialisierung ist, sondern eine 'overloaded'-Funktion. Zweitens, ich weiß nicht, ob ich klar verstehe, was Sie wollen, egal was es ist: http://ideone.com/euoiPN – PcAF

+0

Ja Template-Funktionen können nicht in Template-Klasse spezialisiert werden. Aber was mit dem Tagging gemacht wurde, gibt mir den Effekt der Pseudo-Template-Spezialisierung. ** Meine Voraussetzung ist, dass ich die spezialisierte (getaggte) Funktion in der Painter.cpp-Datei selbst benötige. **. Sie können sehen, ** Meine Versuche, ** zu beheben, wenn Sie gegen Ende meiner Frage lesen. Wie ich in ** meinen Versuchen, ** zu beheben, beschrieben habe, werden die Probleme leicht gelöst, wenn ich einfach die pseudo-spezialisierte Funktion auf 'Painter.h' ohne irgendeine explizite Instantiierung in' Painter.cpp' verschiebe. – Vivek

Verwandte Themen