I don't fully understand all language nuances here, but this allows the
implicit ArrayRef conversions to kick in when e.g. comparing ArrayRef to
a SmallVector. That seems like a good thing.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
Add the inverse equality test too, perhaps - EXPECT_EQ(V1, AR1) ? Though I realize that looks uninteresting & it is, apparently - that's the tricky case for when op overloads are members (though this change doesn't make it a member)
@rsmith - Could you explain why this change makes a difference? I understand why the original implementation (as a standalone function template) doesn't compile (because T can't be deduced for the ArrayRef<T> pattern when given a SmallVector<T>) but how does making it a friend help matters? & is this the right solution, or does it have any drawbacks/missing cases that should be considered? Should this technique be applied in other places?
I've had to revert this because it causes compilation errors on MSVC. I expected this could be a problem, though the error itself is rather puzzling:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xutility(2919): error C2893: Failed to specialize function template 'unknown-type std::equal_to<void>::operator ()(_Ty1 &&,_Ty2 &&) const' C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xutility(2919): note: With the following template arguments: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xutility(2919): note: '_Ty1=const llvm::MDOperand &' C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xutility(2919): note: '_Ty2=const llvm::MDOperand &'
So it MSVC is picking up this friend declaration (or at least, getting confused by it) even when neither of the types are ArrayRefs. That seems like a bug to me, though we may not be able to do anything about it.
(While working on this, I've also realized that I can use the equals member function to avoid explicit ArrayRef cast when I need to compare a ArrayRef with a different type).