2009-06-07 10 views
5

Stavo recentemente cercando di valutare le capacità di sovraccarico/modello del mio operatore e, come piccolo test, ho creato la classe Container di seguito. Mentre questo codice viene compilato correttamente e funziona correttamente in MSVC 2008 (display 11), sia MinGW/GCC che Comeau soffocano sul sovraccarico dello operator+. Poiché mi fido di loro più di MSVC, sto cercando di capire cosa sto facendo male.Sovraccarico dell'operatore binario su una classe di modelli

Ecco il codice:

#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; 
} 

Questo è l'errore Comeau dà:

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". 

Sto avendo un momento difficile cercando di ottenere Comeau/MingGW a giocare a palla, così che è dove Mi rivolgo a voi ragazzi. È passato molto tempo da quando il mio cervello si è sciolto molto sotto il peso della sintassi C++, quindi mi sento un po 'imbarazzato;).

EDIT: Eliminato un errore di lvalue (irrilevante) elencato nel dump iniziale di Comeau.

risposta

5

Ho trovato la soluzione grazie to this forum posting. In sostanza, è necessario disporre di un prototipo di funzione prima di poter utilizzare "amico" all'interno della classe, tuttavia è necessario dichiarare la classe per definire correttamente il prototipo della funzione. Pertanto, la soluzione consiste nell'avere due definizioni di prototipo (della funzione e della classe) nella parte superiore. Il seguente codice compilato in tutte le tre compilatori:

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

Qui il "<>" dopo operator+ deve essere rimossa perché si sta solo dichiarare un nuovo modello, non specializzato di carattere generale. Anche almeno g++ vuole vedere la dichiarazione del modello prima della dichiarazione di amicizia, quindi deve essere spostato prima della dichiarazione di Container. Così il seguente ordine delle dichiarazioni funziona:

// forward declaration of Container<T> 
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); 
     ... 
}; 
0

'operatore +' non è una funzione membro, e non è templato. È solo l'operatore + che prende i parametri dei modelli. '

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

Penso che l'operatore + sia una funzione di modello, non è vero? Un container e un container saranno di due tipi diversi, quindi il compilatore dovrà generare due diverse operatori + funzioni per gestirli. Non significa che l'operatore + è una funzione basata su un modello? –

+0

È * un * modello di funzione. Ma hai ragione ad omettere "<>" dalla definizione del modello. ("<>" viene utilizzato solo quando si specifica un modello di funzione * per chiamare *, e anche in questo caso è necessario solo quando esiste una funzione non modello con lo stesso nome.) –

1

Ho eseguito uno scatto con GCC e l'ho compilato ed eseguito con alcune modifiche. C'erano due cambiamenti che dovevo fare per far felice GCC.

Uno era la dichiarazione della funzione modello amico. È la sua dichiarazione modello separata dalla classe, quindi ho usato U invece della classe Container 'T there. Mi sono anche liberato dello <> dopo l'operatore +. Non penso che ti serviranno quelli a meno che tu non stia scrivendo una specializzazione per i modelli.

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

Due, la linea

non ha volato con GCC perché si sta chiedendo di memorizzare un riferimento a un temporaneo (il risultato della somma). Ho rimosso la e commerciale in modo che ci sia un posto dove archiviare il risultato.

Ho visto il tuo messaggio proprio ora, che funziona anche a causa delle dichiarazioni in avanti. Credo che lo pubblicherò comunque come un'alternativa che non li richiede. Certo che ho provato solo in GCC ...

+0

Ho trovato questo in un altro annuncio online e questo sarebbe il mio preferenza personale dei due (più concisa). – GRB

+0

Questo consentirà l'accesso a tutte le specializzazioni del modello (quindi l'operatore + potrebbe accedere ai privati ​​del contenitore ). Il codice del richiedente vuole concedere l'accesso solo all'operatore + (solo l'operatore + può accedere ai privati ​​del Container ) –

+0

@litb: Ho visto anche questo problema menzionato, ma ho difficoltà a configurare uno scenario del genere. Potresti fornire uno snippet di codice di esempio in cui il sovraccarico int accede ai membri privati ​​di un float? – GRB

1

Sarebbe meglio definire la funzione direttamente nella classe. Inoltre, è necessario passare i parametri come riferimenti const.

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