Tested only in GCC and Clang, the presence of a pass-by-value copy assignment operator in the base class (useful when implementing the copy-and-swap (or copy-and-move) idiom) causes the copy assignment operator in the derived class to be implicitly deleted.
Clang and GCC agree on this; why is this the case?
Example code:
#include <string>
#include <iostream>
struct base {
base() {
std::cout << "no-arg constructor\n";
}
base(const base& other) :
str{other.str} {
std::cout << "copy constructor\n";
}
base(base&& other) :
str{std::move(other.str)} {
std::cout << "move constructor\n";
}
base& operator=(base other) {
std::cout << "copy assigment\n";
str = std::move(other.str);
return *this;
}
base& operator=(base&& other) {
std::cout << "move assigment\n";
str = std::move(other.str);
return *this;
}
std::string str;
};
struct derived : base {
derived() = default;
derived(derived&&) = default;
derived(const derived&) = default;
derived& operator=(derived&&) = default;
derived& operator=(const derived&) = default;
};
derived foo() {
derived ret;
ret.str = "Hello, world!";
return ret;
}
int main(int argc, const char* const* argv) {
derived a;
a.str = "Wat";
a = foo(); // foo() returns a temporary - should call move constructor
return 0;
}
operator=(base other)
is not a copy-assignment operator, it's just a regular assignment operator. Copy-assignment operators only takebase const&
as an argument. – 0x499602D2derived& operator=(derived&& other)
would normally attempt to callbase::operator=(std::move(other))
, but that call is ambiguous because you defined two assignment operators inbase
, both accepting rvalues. – Igor Tandetnik