This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 114b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-05-06


444. Overriding and the generated copy assignment operator

Section: 11.4.6  [class.copy.assign]     Status: NAD     Submitter: Kerch Holt     Date: 26 Nov 2003

EDG (and g++, for that matter) picks the explicit copy assignment operator, which we think is wrong in this case:

#include <stdio.h>
struct D;   // fwd declaration
struct B {
    D& operator=(D&);
};
struct D : B {
    D() {}
    D(int ii) { s = ii; }
    using B::operator=;
    int s;
};
int main() {
    D od, od1(10);
    od = od1; // implicit D::operator=(D&) called, not BASE::operator=(D&)
}
D& B::operator=(D& d) {
    printf("B::operator called\n");
    return d;
}

If you look at 11.4.5.3 [class.copy.ctor] paragraph 10 it explicitly states that in such a case the "using B::operator=" will not be considered.

Steve Adamczyk: The fact that the operator= you declared is (D&) and not (const D&) is fooling you. As the standard says, the operator= introduced by the using-declaration does not suppress the generation of the implicit operator=. However, the generated operator= has the (const D&) signature, so it does not hide B::operator=; it overloads it.

Kerch Holt: I'm not sure this is correct. Going by 12.8 P10 first paragraph we think that the other form "operator=(D&)" is generated because the two conditions mentioned were not met in this case. 1) there is no direct base with a "const [volatile] B&" or "B" operator 2) And no member has a operator= either. This implies the implicit operator is "operator=(D&)". So, if that is the case the "hiding" should happen.

Also, in the last paragraph it seems to state that operators brought in from "using", no matter what the parameter is, are always hidden.

Steve Adamczyk: Not really. I think this section is pretty clear about the fact that the implicit copy assignment operator is generated. The question is whether it hides or overloads the one imported by the using-declaration.

Notes from the March 2004 meeting:

(a) Class B does get an implicitly-generated operator=(const B&); (b) the using-declaration brings in two operator= functions from B, the explicitly-declared one and the implicitly-generated one; (c) those two functions overload with the implicitly-generated operator=(const D&) in the derived class, rather than being hidden by the derived-class function, because it does not match either of their signatures; (d) overload resolution picks the explicitly-declared function from the base class because it's the best match in this case. We think the standard wording says this clearly enough.