Compilation triggers the following warning on the line with the weakRef1 == weakRef2 test:
Main.cpp:37:22: ISO C++20 considers use of overloaded operator '==' (with operand types 'juce::WeakReference<juce::Component>' and 'juce::WeakReference<juce::Component>') to be ambiguous despite there being a unique best viable function.
juce_WeakReference.h:119:10: Ambiguity is between a regular call to this operator and a call with the argument order reversed
I’m not entirely sure what it is complaining about…
Follow up: today I learned, that starting from C++20 the compiler can look up operator overloads also considering the operands in reverse order, see: Comparisons in C++20
Still I can’t conjure what’s needed to avoid that warning though
Ah, yes!
Thanks to your observation, I realized that the fact that the existence of only
WeakReference::operator==(ObjectType*)
means that when comparing two WeakReferences (as opposed to one WeakReference and one raw pointer), the compiler could call it either as
weakRef1 == weakRef2.get()
or otherwise
weakRef2 == weakRef1.get()
And it is warning about this ambiguity because in one case .get() is called on weakRef1 and in the other it is called on weakRef2, breaking the simmetry.
The warning goes away if I add a better candidate for the comparison between two WeakReference instances, in the form of this code added to the WeakReference class definition:
Caveat: setting comparison operators to “= default” is a C++20 feature, thus the code above should be put inside appropriate guards to be backwards compatible with earlier standards.
Even if I would have liked the idea of adding operator==() = default better (it’s more C++20-y), this solution has a few practical advantages that better suit my current situation:
This code is backwards compatible with C++17 (I have some projects that share the same copy of JUCE, that are not ready to be bumped to C++20 yet)
Looking at the implementation of the other (in)equality operators with raw pointers, I’m confident this is the intended behavior when comparing two WeakReferences.
I’m not equally confident that the same results are obtained using the = default alternative.
In the latter case, the implementation is left to the compiler which does it by comparing the instance members, and that means delegating the comparison to the comparison between WeakPointer::SharedRef instances. For now they are ReferenceCountedObjectPtr under the hood, which seem to do the right thing, but who knows what may silently change in the future if I merge some more JUCE code down the line?