2015-03-28 16 views
6

To nie jest duplikat. Sprawdziłem wiele odpowiedzi, FAQ i jeszcze więcej. Nic z tego nie mówiło mi o nowościach. Oto uproszczony kod. To minimum, aby uzyskać i wyjaśnić błąd.Operatory szablonów nie działają pozornie na niejednoznaczność.

/*** 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; 
} 

Kiedy komentować linię pod [!] IN, błąd jest friends can only be classes or functions (Clang ++) lub declaration of ‘operator+’ as non-function (g ++).

Wydaje mi się, że kompilatorzy błędnie traktują dwóch operatorów. O ile nauczyłem się operatora przeciążającego rzeczy, operatory jednoargumentowe i binarne są całkowicie niezależne i mogą być unikalnie rozróżniane na podstawie ich liczby argumentów:.

Dlaczego więc wystąpił błąd? Uczynienie operatora unarnego przyjacielem za pomocą standardowej praktyki powoduje, że kod kompiluje się dobrze na obu kompilatorach.

+2

Interesujące. Jeśli umieścisz jednokierunkowy 'operator +' pod deklaracją znajomego binarnego, zarówno gcc, jak i clang skompilują go bez zarzutu, jeśli umieścisz go powyżej, otrzymasz błąd kompilatora. – Wintermute

Odpowiedz

4

Kiedy deklarujesz coś w zakresie, ukrywa ona delikacje o tej samej nazwie w szerszym zakresie. Tutaj deklaracja członka operator+ ukrywa tożsamość osoby nie będącej członkiem. Tak więc deklaracja friend odnosi się do członka, a nie do osoby niebędącej członkiem, stąd błąd.

Musisz określić nazwę, jeśli chcesz zapoznać się zarówno w tym samym zakresie:

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

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

Wygląda na to, że prawdziwy nagłówek PO zawiera plik źródłowy na dole. – chris

+1

@chris: Tak jest. To jest wstrętne. –

+0

Występuje dość często, ale zazwyczaj rozszerzenie to coś innego niż cpp. Czy libstdC++ nie używa Tpp? – chris

Powiązane problemy