https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93147

            Bug ID: 93147
           Summary: std::tuple of empty structs with member equality
                    operators has ambiguous equality operator
           Product: gcc
           Version: 9.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kholdstare0.0 at gmail dot com
  Target Milestone: ---

The following code:

    #include <tuple>

    struct A {
        bool operator == (A) const { return true; }
    };

    struct B {
        bool operator == (B) const { return true; }
    };

    using Tuple = std::tuple<A, B>;

    bool example(Tuple a, Tuple b)
    {
        return a == b;
    }

Results in an error:

    <source>: In function 'bool example(Tuple, Tuple)':
    <source>:18:21: error: request for member 'operator==' is ambiguous
       18 |         return a == b;
          |                     ^
    <source>:4:14: note: candidates are: 'bool A::operator==(A) const'
        4 |         bool operator == (A) const { return true; }
          |              ^~~~~~~~
    <source>:8:14: note:                 'bool B::operator==(B) const'
        8 |         bool operator == (B) const { return true; }
          |              ^~~~~~~~
    Compiler returned: 1

Here is the godbolt link, with the preprocessor output on the side: 
https://godbolt.org/z/a4TuB3

Some things to note:
 - This compiles fine with Clang
 - If the structs are non-empty, this also compiles fine
 - If the comparison operators are non-members this also compiles fine
 - The failure is exactly the same going back all the way to gcc 4

My suspicion is that tuple indirectly inherits the types `A` and `B`, and even
though it may be private inheritance, the compiler still finds both comparison
operators and considers them ambiguous. GCC tries to implicitly convert
`std::tuple<A, B>` into `A` and `B` to call `operator ==`.

Reply via email to