The most popular operator which should return reference is operator=
class Alpha
{
    int x;
    int y;
    std::string z;
  public:
    void print()
        { cout << "x " << x << " y " << y << "  " << z << '\n'; }
    Alpha(int xx=0, int yy=0, std::string zz=""): x(xx), y(yy), z(zz) {}
    Alpha operator=(Alpha& another)
    {
        x = another.x;
        y = another.y;
        z = another.z;
        return *this;
    }
};
int main()
{
    Alpha a(3,4,"abc"),b,c;
    b=c=a;
    return 0;
}
Clang says this:
clang++-3.6 new.cxx -o new new.cxx:70:3: error: no viable overloaded '=' b=c=a; ~^~~~ new.cxx:34:8: note: candidate function not viable: expects an l-value for 1st argument Alpha operator=(Alpha& another) ^ 1 error generated.
gcc this:
new.cxx:34:8: note: no known conversion for argument 1 from ‘Alpha’ to ‘Alpha&’
But I can't understand what's the problem in theory. What I think happens:
c. It receives object a by reference, copies it's values to c and returns anonymous copy of it's self (of object c): Copy soncstructor is called.b. It requires rvalue ref, but we have only written lvalue reference, so the error occurs.I have added rval operator= and copy constructor, which receives lvalue reference and everything works, now I have no idea why (I should have written rvalue copy constructor which receive const Alpha& s or Alpha&& s):
class Alpha
{
    int x;
    int y;
    std::string z;
  public:
    void print()
    { cout << "x " << x << " y " << y << "  " << z << '\n'; }
    Alpha(int xx=0, int yy=0, std::string zz=""): x(xx), y(yy), z(zz) {}
    //Alpha(Alpha&& s): x(s.x), y(s.y), z(s.z) {}
    Alpha(Alpha&& ) = delete;
    Alpha(Alpha& s): x(s.x), y(s.y), z(s.z) {}
    Alpha operator=(Alpha& another)
    {
        x = another.x;
        y = another.y;
        z = another.z;
        return *this;
    }
    Alpha operator=(Alpha&& another)
    {
        x = another.x;
        y = another.y;
        z = another.z;
        return *this;
    }
};
                This signature for an assignment operator
Alpha operator=(Alpha& another)
is unusual in two ways. The first is that it returns a copy of the assigned-to object. Very rare to do that. The other is that it accepts a non-const reference as a parameter.
The non-const reference makes it not accept temporary objects as a parameter (as those will only bind to a const lvalue reference).
In combination this means that the temporary returned from the first operator= can not be used as a parameter to the second operator=.
Your options are to either return a reference, or to make the parameter Alpha const&. Both options would work individually, or in combination.
The third option, as you found out, is to explicitly add a move assignment operator, using Alpha&& that specifically accepts temporaries. 
The standard way though is to declare the copy assignment operator
Alpha& operator=(Alpha const& other);
unless you have very specific reasons for selecting another signature.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With