Search code examples
c++usingcrtp

Copy assignment operator in CRTP - gcc vs clang and msvc


The following code (see this question) results in an error when compiled by gcc 8.2, but is accepted by clang 7.0.0 and msvc 15.9.0 preview 3:

template<typename T>
struct B
{
    void operator=(const T&) { }
    void foo() { }
};

struct D : public B<D>
{
    using B<D>::operator=;
    using B<D>::foo;       // hidden by D::foo
    void foo() { }
};

int main()
{
    D d1, d2;
    d1 = d2;
    d1.foo();
    return 0;
}

The error message generated by gcc is:

<source>: In function 'int main()':
<source>:8:8: error: 'constexpr D& D::operator=(const D&)' cannot be overloaded with 'void B<T>::operator=(const T&) [with T = D]'
struct D : public B<D>
       ^
<source>:4:8: note: previous declaration 'void B<T>::operator=(const T&) [with T = D]'
  void operator=(const T&) { }
       ^~~~~~~~

We have two assignment operators in D, the first one is the default-generated, the second one is introduced with using. They have the same signature, so the overloading fails. But why is operator= from the base class simply not hidden by the one in the derived, as it happens for the foo() member function?

What is going on here? Why only gcc complains? Should it complain?


Solution

  • GCC is wrong here: this is specially called out as a situation where no overloading occurs. (Neither does it happen for other member functions, of course, as you said.)