3

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.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
hob-B1T
  • 73
  • 3
  • "I have the german version of VC++ and the g++ errors span over many lines." English ones usually aren't that much better. – user4581301 Feb 21 '17 at 21:01

1 Answers1

3

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;
}

Live Example

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.

Community
  • 1
  • 1
TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • Thank you very much, this helps for both problems. The const for the member version was just something I forgot in the extracted code. But I never thought that a misplaced const can create so many different errors. The g++ error messages mentioned something about const, but I didn't understand it. Now it's a bit more clear and I have to understand this in details, thanks again. – hob-B1T Feb 21 '17 at 20:55
  • 1
    @hob-B1T you're welcome, if you find this answer OK, please use the "accept" button – TemplateRex Feb 21 '17 at 20:55
  • The third error is that that operator template will never be used. – T.C. Feb 22 '17 at 06:35
  • 1
    ...and the reason it will never be used (absent an explicit call) is that `T` isn't deducible, not that there's a member operator. – T.C. Feb 22 '17 at 07:57