Reputation: 73
I've problems overloading operator==, different compiler errors using VC++(2015) and g++ 5.4.0 (--std==c++14). Here's the code (this is just an extract of a more complex situation in my real code base):
#include <vector>
template<typename T>
struct A {
struct B {
std::vector<T> _elements;
// Internal cmp op.
bool operator==(const B &other) {
return _elements == other._elements;
}
};
std::vector<B> _entries;
};
// External cmp op.
template<typename T>
inline bool operator==(typename const A<T>::B &l, typename const A<T>::B & r) {
return l._elements == r._elements;
}
int main() {
A<int>::B b0, b1;
b0.operator==(b1); // a
operator==<int>(b0, b1); // b
b0 == b1; // c
std::vector<A<int>::B> v0, v1;
std::equal(v0.begin(), v0.end(), v1.begin()); // d
v0 == v1; // e
return 0;
}
I do not add the error messages, because I have the german version of VC++ and the g++ errors span over many lines.
VC++ gives an error on (e). I don't understand why, because vector<>::operator== seems to call std::equal internally and (d) compiles fine. Why does this fail?
g++ fails to accept my external operator==(), so totally fails to compile this short code. I have no idea how to write an external operator==() for A<T>::B that works with both compilers.
I haven't tried clang yet.
Many thanks.
Upvotes: 3
Views: 91
Reputation: 70546
There were two errors in your program:
// Internal cmp op.
bool operator==(const B &other) const {
///// <- here
return _elements == other._elements;
}
should be a const
member and the keyword const
cannot appear just behind the typename
:
// External cmp op.
template<typename T>
inline bool operator==(typename A<T>::B const& lhs, typename A<T>::B const& rhs)
///// <- here -> ////
{
return lhs._elements == rhs._elements;
}
Note that the placement of const
is usually fairly liberal in C++, e.g. you can write both const typename A<T>::B & lhs
and typename A<T>::B const& lhs
, but the form you chose, typename const A<T>::B & lhs
is not allowed.
Also note that you want to write either a member operator==
or a non-member operator==
, but never both. In your case, because T
is not deducible in typename A<T>::B
, you have to write the ugly operator==<int>(b0, b1)
to select the non-member.
I would remove the non-member template operator==
and add to your class template A<T>
a non-member
bool operator==(const A &other) const {
return _entries == other._entries;
}
so that you can also compare objects of A<int>
. Note that this will call the standard library operator==
for std::vector
which in turn will call your operator==
for B
.
Upvotes: 3