2015-03-28 20 views
6

Questo non è un duplicato. Ho controllato molte risposte, le FAQ e altro. Niente di ciò mi ha detto notizie. Ecco il codice semplificato. È il minimo per ottenere e spiegare l'errore.non riescono apparentemente in ambiguità

/*** Polynomial.hpp ********************************************************/ 

namespace Modulus 
{ 
// Forward declaration of the types and non-inline template friend functions. 

template <typename T> 
    class Polynomial; 

template <typename T> 
    Polynomial<T> operator + 
     (Polynomial<T> const & p, 
     Polynomial<T> const & q); 
} 

namespace Modulus 
{ 

template <typename T> 
class Polynomial 
{ 
public: 
    Polynomial() { } 

    // [!] when you comment this in, you get the error. 
    //Polynomial  operator +  () const { return *this; } 

    friend Polynomial operator + <> (Polynomial const & p, 
            Polynomial const & q); 
}; 

} // namespace 

// Template: include .cpp file. 
    //#include "Polynomial.cpp" 
///^ It is commented out, for compiling in one file. 


/*** Polynomial.cpp ********************************************************/ 

namespace Modulus 
{ 

template <typename T> 
Polynomial<T> 
    operator + (Polynomial<T> const & p, 
       Polynomial<T> const & q) 
{ 
    return Polynomial<T>(); 
} 

} // namespace 


/*** main.cpp **************************************************************/ 


//#include "Polynomial.hpp" 

using namespace Modulus; 

int main() 
{ 
    Polynomial<int> p; 
    p + p; 
    return 0; 
} 

Quando io commento la linea sotto [!] in, l'errore che ottengo è friends can only be classes or functions (Clang ++) o declaration of ‘operator+’ as non-function (g ++).

Per me, sembra che i compilatori scambino i due operatori. Per quanto ho appreso il sovraccarico dell'operatore, gli operatori unari e binari sono completamente indipendenti e possono essere distinti in modo univoco dal loro numero di argomenti.

Quindi perché si verifica l'errore? Rendere l'operatore unario un amico usando la pratica standard, rende il codice compilato bene su entrambi i compilatori.

+2

Interessante. Se metti l'unario 'operator +' sotto la dichiarazione friend di binary, sia gcc che clang lo compilano senza lamentele, se lo metti sopra, ottieni un errore del compilatore. – Wintermute

risposta

4

Quando si dichiara qualcosa in un ambito, nasconde le delcarazioni con lo stesso nome in qualsiasi ambito più ampio. Qui, la dichiarazione del membro operator+ nasconde quella del non membro. Quindi la dichiarazione friend fa riferimento al membro, non al non membro, quindi all'errore.

Avrai bisogno di qualificare il nome se si desidera fare riferimento ad entrambi nello stesso ambito:

Polynomial  operator +  () const { return *this; } 

friend Polynomial Modulus::operator + <> (Polynomial const & p, Polynomial const & q); 
        ^^^^^^^^^ 
+0

Sembra che l'intestazione reale dell'OP includa il file sorgente in basso. – chris

+1

@chris: così fa. Cattiveria. –

+0

È abbastanza comune, ma in genere l'estensione sarebbe diversa da cpp. Non libstdC++ usa tpp? – chris