Операторские перегрузки, реализованные как функции-члены, не допускают неявного преобразования их левого операнда, являющегося объектом, для которого они вызываются.
Это всегда помогает записать явный вызовперегрузка оператора, чтобы лучше понять, что именно он делает:
Foo<Bar> e (Bar{true});
Bar f = {false};
// Pretty explicit: call the member function Foo<Bar>::operator==
if(e.operator ==(f)) { /* ... */ }
Это нельзя спутать с оператором сравнения в Bar
, потому что это потребует неявного преобразования левой части, котораяневозможно.
Вы можете вызвать неоднозначность, аналогичную той, которую вы видите со встроенными типами при определении Bar
и его операторе сравнения, например:
struct Bar { bool m; };
// A free function allows conversion, this will be ambiguous:
bool operator==(const Bar&, const Bar&)
{
return false;
}
Это хорошопродемонстрировано и объяснено в Скотт Мейерс Эффективный C ++ , пункт 24.