Search code examples
c++g++language-lawyermultiple-inheritancecomparison-operators

Ambiguity error accessing equality comparison operator in G++


In case of multiple inheritance if all parent classes have their own equality comparison operator ==, and the child class has a (friend) function operator ==, as in the example:

struct A {
    bool operator ==(const A&) const = default;
};

struct B {
    bool operator ==(const B&) const = default;
};

struct C : A, B {};

constexpr bool operator ==(const C&, const C&) { return true; }

static_assert( C{} == C{} );

GCC prints the following error about ambiguity in an attempt to compare child objects:

 error: request for member 'operator==' is ambiguous
   13 | static_assert( C{} == C{} );
 note: candidates are: 'bool B::operator==(const B&) const'
 note:                 'bool A::operator==(const A&) const'

Demo: https://gcc.godbolt.org/z/W3qer376d

This error looks surprising, since operator ==(const C&, const C&) shall be preferred as the most suitable to the actual arguments. Is it simply a defect in GCC?


Solution

  • Indeed the global operator operator==(const C&, const C&) has priority. However the compiler "want to know" all the possibilities in order to decide: In other words: as soon as you try to use the operator== the compiler requires you to have no ambiguities, even if the required alternative is not between the ambiguous one.


    struct C : A, B { using A::operator==; }; 
    

    This resolves the ambiguity and allows you to use the global operator==

    https://onlinegdb.com/nxMjPN4NC

    #include <iostream>
    
    struct A {
        bool operator ==(const A&) const { std::cout << "A" << std::endl; return true; };
    };
    
    struct B {
        bool operator ==(const B&) const { std::cout << "B" << std::endl; return true; };
    };
    
    struct C : A, B 
    {
        //using A::operator==; // Uncomment this to make it work.
    };
    
    bool operator ==(const C&, const C&) { std::cout << "C" << std::endl; return true; }
    
    int main()
    {
        C c1, c2;
        
        c1==c2;
    
        return 0;
    }
    

    Result (when resolved):

    C