tworzy instancję ::operator*<A>
. W ramach tej funkcji mamy wyrażenie: b * a
, które, jeśli spojrzysz na typy (uproszczone), to A * float
. W tym momencie kompilator musi dokonać wyboru. Czy ta *
powinna być globalną funkcją ::operator*<float>
(ponieważ argumentem po prawej stronie jest float
), czy powinien to być A::operator*
? Dla nas, ludzi, jasne jest, że powinno to być A::operator*
, ale z punktu widzenia kompilatora nie jest to od razu jasne.
Co robi kompilator? Najpierw próbuje znaleźć wszystkie funkcje operator*
, które mogą być używane (po czym próbuje dokładnie określić, którego użyć). Jedną z funkcji operator*
, którą można zastosować, jest ::operator*<float>
. Ale czekaj, co to jest ::operator*<float>
? To jest float *(float, const float&)
! I nie możemy tego zrobić! Nie można przeciążać operatorów dla typów pierwotnych (wyobraź sobie chaos, jeśli przeładowałeś int +(int, int)
, więc robisz coś zupełnie innego niż to, co wszyscy oczekiwali).
W tym momencie program jest źle sformułowany. Sam fakt, że kompilator próbuje nawet utworzyć instancję ::operator*<float>
, unieważnia program jako całość. Więc co możemy zrobić? Poinformować kompilator dokładnie, co robić:
template<class T>
T operator*(float a, const T& b)
{
// This prevents the compiler from instantiating ::operator*<float>
return b.operator*(a);
// The above is meant to illustrate how the fix needs to work: it needs
// to avoid instantiating ::operator*<float>. Other methods can be used
// (like SFINAE) that might be more elegant (check out Walter's answer
// in the duplicate: https://stackoverflow.com/a/18596809/1287251), but
// in the end any solution used must avoid ::operator*<float>.
}
struct A{
A operator*(float b) const
{
A a;
return a;
}
};
int main()
{
A a;
2.0f * a;
}
W skrócie, aby odpowiedzieć na pytanie: nie, kod nie jest prawidłowy. Musisz uniemożliwić kompilatorowi próbę utworzenia instancji ::operator*<float>
.
This is explained by @dyp in the comments i by @TemplateRex in the duplicate question. Jednak musiałem przeczytać ich odpowiedzi kilka razy, zanim zrozumiałem, co mają na myśli. Próbowałem uprościć rzeczy w tej odpowiedzi. Jeśli mogę to poprawić, proszę dać mi znać!
http://stackoverflow.com/questions/18596412/strange-error-with-a-templated-operator-overload Może pomóc? – IllusiveBrian
Myślę, że @Namfuak znalazł duplikat: wyrażenie 'b * a' próbuje utworzyć szablon funkcji operatora, który prowadzi do' T' wydedukowanego jako 'float', a wytworzona specjalizacja (funkcja operatora) jest niedopuszczalna uformowany, ponieważ nie ma parametru typu klasy/wyliczenia lub jego odwołania. Wygląda na to, że nie występuje awaria substytucji, tj. Poważny błąd. Zobacz [powyżej.oper]/1 i/6. – dyp
Próbowałem dalej minimalizować twój kod i usunięto 'A :: operator *' ... ale zauważyłem, że to uniemożliwiło GCC skompilowanie kodu. Interesujące ... –