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