You might be tempted to make a copy-assign return void statement if you don't need chained assignments (as shown in other answers) anyway. After all, seconded assignments are often difficult to read and understand, so they cannot be considered an improvement.
However, the often forgotten aspect is that void operator=(Poly& const) means that your type will no longer fulfill the CopyAssignable concept, which requires a T& return type.
A type that does not conform to the CopyAssignable concept cannot be officially used for some operations with a standard container, for example std::vector::insert , which means that the next seemingly innocent piece of code gives undefined behavior, although this is probably fine working:
#include <vector> struct Poly { void operator=(Poly const&) {} // Poly is not CopyAssignable }; int main() { std::vector<Poly> v; Poly p; v.insert(v.begin(), p); // undefined behaviour }
As the C ++ standard explains in section 17.6.4.8/2.3, which talks about restrictions on programs that use the standard library:
(...) effects are undefined in the following cases:
(...) for types used as template arguments when instantiating template components , if type operations do not implement the semantics of the applicable requirements of subclause (...).
Of course, it is precisely because of the undefined behavior that the compiler is allowed to ignore the error and force the program to behave nicely, corresponding to the obviously intended behavior. But this is not required.
You should also bear in mind that you cannot predict all future uses of your Poly type. Someone might write some template function, such as:
template <class T> void f(T const& t) { T t2; T t3 = t2 = t;
This function will not work with your Poly class.
Just don't break this C ++ convention and you won't run into problems.