#include <iostream>
using namespace std;

struct A {
    std::string s;
    A(const std::string& s) : s(s) {}
    A(const A& o) : s(o.s) { std::cout << "move failed!\n"; }
    A(A&& o) : s(std::move(o.s)) {}
    A& operator=(const A&) { std::cout << "copy assigned\n"; return *this; }
    A& operator=(A&& other) {
        std::cout << s << " " << other.s << endl;
        s = std::move(other.s);
        std::cout << "move assigned\n";
        std::cout << s << " " << other.s << endl;
        return *this;
    }
};

A f(A a) { return a; }

struct B : A {
	B(const std::string& s) : A(s) { }
    std::string s2;
    int n;
    // implicit move assignment operator B& B::operator=(B&&)
    // calls A's move assignment operator
    // calls s2's move assignment operator
    // and makes a bitwise copy of n
};

int main()
{
    A a1("foo"), a2("bar");
    std::cout << "Trying to move-assign A from rvalue temporary\n";
    a1 = f(A("asda")); // move-assignment from rvalue temporary
    std::cout << "Trying to move-assign A from xvalue\n";
    a2 = std::move(a1); // move-assignment from xvalue

    std::cout << "Trying to move-assign B\n";
    B b1("foo"), b2("bar");
    std::cout << "Before move, b1.s = \"" << b1.s << "\"\n";
    b2 = std::move(b1); // calls implicit move assignment
    std::cout << "After move, b1.s = \"" << b1.s << "\"\n";
}