2009-06-07 16 views
5

Ich habe kürzlich versucht, meine Operatorüberladung/Template-Fähigkeiten zu messen und als kleinen Test die Container-Klasse unten erstellt. Während dieser Code gut kompiliert und unter MSVC 2008 korrekt funktioniert (zeigt 11 an), ersticken sowohl MinGW/GCC als auch Comeau die operator+ Überlastung. Da ich ihnen mehr als MSVC vertraue, versuche ich herauszufinden, was ich falsch mache. HierBinärer Operator überladen auf einer Vorlagenklasse

ist der Code:

#include <iostream> 

using namespace std; 

template <typename T> 
class Container 
{ 
     friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs); 
    public: void setobj(T ob); 
    T getobj(); 
     private: T obj; 
}; 

template <typename T> 
void Container<T>::setobj(T ob) 
{ 
    obj = ob; 
} 

template <typename T> 
T Container<T>::getobj() 
{ 
    return obj; 
} 

template <typename T> 
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 
{ 
     Container<T> temp; 
     temp.obj = lhs.obj + rhs.obj; 
     return temp; 
} 

int main() 
{  
    Container<int> a, b; 

a.setobj(5); 
    b.setobj(6); 

Container<int> c = a + b; 

cout << c.getobj() << endl; 

    return 0; 
} 

Dies ist der Fehler Comeau gibt:

Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2 
Copyright 1988-2008 Comeau Computing. All rights reserved. 
MODE:strict errors C++ C++0x_extensions 

"ComeauTest.c", line 27: error: an explicit template argument list is not allowed 
      on this declaration 
    Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 
      ^

1 error detected in the compilation of "ComeauTest.c". 

Ich bin eine harte Zeit versucht, Comeau/MingGW zu bekommen, Ball zu spielen, so das ist, wo Ich wende mich an euch. Es ist lange her, dass mein Gehirn unter dem Gewicht der C++ - Syntax so stark geschmolzen ist, und ich fühle mich ein wenig peinlich berührt;).

BEARBEITEN: Beseitigt einen (irrelevanten) Lvalue-Fehler, der im ursprünglichen Comeau-Dump aufgelistet ist.

Antwort

5

Ich fand die Lösung dank to this forum posting. Im Wesentlichen benötigen Sie einen Funktionsprototyp, bevor Sie in der Klasse "friend" verwenden können. Sie müssen jedoch auch die Klasse deklarieren, um den Funktionsprototyp richtig zu definieren. Daher besteht die Lösung darin, zwei Prototypdefinitionen (der Funktion und der Klasse) oben zu haben. Der folgende Code kompiliert unter allen drei Compiler:

#include <iostream> 

using namespace std; 

//added lines below 
template<typename T> class Container; 
template<typename T> Container<T> operator+ (Container<T>& lhs, Container<T>& rhs); 

template <typename T> 
class Container 
{ 
     friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs); 
     public: void setobj(T ob); 
       T getobj(); 
     private: T obj; 
}; 

template <typename T> 
void Container<T>::setobj(T ob) 
{ 
     obj = ob; 
} 

template <typename T> 
T Container<T>::getobj() 
{ 
     return obj; 
} 

template <typename T> 
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs) 
{ 
     Container<T> temp; 
     temp.obj = lhs.obj + rhs.obj; 
     return temp; 
} 

int main() 
{  
    Container<int> a, b; 

    a.setobj(5); 
    b.setobj(6); 

    Container<int> c = a + b; 

    cout << c.getobj() << endl; 

    return 0; 
} 
2
template <typename T> 
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 

Hier wird die „<>“ nach operator+ entfernt werden soll, da Sie nur eine neue Vorlage zu erklären, nicht einen allgemeinen spezialisiert. Auch mindestens g++ möchte die Template-Deklaration vor der Friend-Deklaration sehen, also muss sie vor der Deklaration von Container verschoben werden. Die folgende Reihenfolge der Deklarationen funktioniert also:

0

'Operator +' ist keine Member-Funktion, und es ist nicht templated. Es ist nur der Operator +, der Template-Parameter verwendet.

template <typename T> 
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs) 
+1

Ich denke, der Operator + ist eine Vorlagenfunktion, nicht wahr? Ein Container und ein Container werden zwei unterschiedliche Typen sein, so dass der Compiler zwei mit ihnen umgehen verschiedene Operator + Funktionen generieren müssen. Bedeutet das nicht, dass Operator + eine Template-Funktion ist? –

+0

Es * ist * eine Funktionsvorlage. Aber Sie haben Recht, indem Sie das "<>" aus der Definition der Vorlage auslassen. („<>“ Wird nur verwendet, wenn eine Funktionsschablone * Angabe von * anrufen, und selbst dann ist nur notwendig, wenn eine Nicht-Template-Funktion mit dem gleichen Namen existiert.) –

1

gab ich dieses einen Schuss unter GCC und bekam es mit ein paar Änderungen zu kompilieren und auszuführen. Es gab zwei Änderungen, die ich machen musste, um GCC glücklich zu machen.

Einer war die Deklaration der Freundschablonenfunktion. Es ist eine eigene Template-Deklaration getrennt von der Klasse eins, also habe ich statt der Container-Klasse 'T dort U verwendet. Ich habe auch die <> nach dem Operator + losgeworden. Ich glaube nicht, dass du diese brauchen würdest, außer du schreibst eine Template-Spezialisierung.

 template<typename U> 
     friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs); 

Zwei, die Linie

nicht mit GCC hat fliegen, weil Sie einen Verweis auf ein temporäres zu speichern sind gefragt (das Ergebnis der Addition). Ich habe das kaufmännische Und-Zeichen entfernt, sodass es einen Platz zum Speichern des Ergebnisses gibt.

Ich habe gerade Ihren Beitrag gesehen, der auch wegen der Vorwärtsdeklarationen funktioniert. Ich schätze, ich werde das trotzdem als eine Alternative veröffentlichen, die sie nicht benötigt. Natürlich habe ich nur in GCC getestet ...

+0

ich diese Online in einem anderen Posting gefunden und das wäre mein persönliche Präferenz der beiden (prägnanter). – GRB

+0

Dieser wird Zugriff auf alle Vorlage Spezialisierungen gewähren (so operator + könnte Gemeinen von Containern zugreifen ). Der Code des Fragestellers möchte nur dem Operator + Zugriff gewähren (nur Operator + kann auf die Container zugreifen) –

+0

@litb: Ich habe dieses Problem auch erwähnt, aber ich habe Probleme, ein solches Szenario einzurichten. Könnten Sie ein Beispielcode-Snippet angeben, bei dem die Überladung auf die privaten Mitglieder eines Floats zugreift? – GRB

1

würden Sie besser die Funktion direkt in der Klasse zu definieren sein. Außerdem sollten Sie die Parameter als const Referenzen übergeben.

template <typename T> 
class Container 
{ 
public: 
    friend Container operator+ (Container const & lhs, Container const & rhs) 
    { 
     // ... 
    } 
}; 
Verwandte Themen