// http://stackoverflow.com/questions/19826045/trying-to-write-move-constructor-in-terms-of-move-assignment/19846215#19846215
// https://i...content-available-to-author-only...e.com/AnwDvD
#include<algorithm>
#include<cassert>
#include<cstring>
#include<iostream>

class String
{
    char*   m_data;
    int     m_len;
    public:
    const volatile String&& operator=(String&) volatile const  = delete; // make it as undesirable as possible!
    void swap(String& rhs) throw()
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        std::swap(m_data, rhs.m_data);
        std::swap(m_len,  rhs.m_len);
    }
    template<typename T>
    String& operator=(T templated_copy_and_swap) {
         std::cout << __PRETTY_FUNCTION__ << "  (Templated  ) Assignment by (optional) copy and (not-optional) swap" << std::endl;
         templated_copy_and_swap.swap(*this);
         return *this;
    }
    String(String&& move_constructor) throw()  // The move constructor, we wish to use operator= here
        : m_data(NULL)
        , m_len(0)
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        //move_constructor.swap(*this); // This was the original line we wish to replace
       operator=(std::move(move_constructor)); // It works!
    }
    String& operator=(String && move_assignment) {
         std::cout << __PRETTY_FUNCTION__ << std::endl;
         move_assignment.swap(*this);
         return *this;
     }

     /* Below are just some other constructors that are required
      * to build a working demonstration
      */
     String(const String &copy_constructor) {
         std::cout << __PRETTY_FUNCTION__ << "     Copy constructor" << std::endl;
         m_len = copy_constructor.m_len;
         m_data = new char[m_len+1];
         strncpy(m_data, copy_constructor.m_data, m_len+1);
    }
    ~String() {
         std::cout << __PRETTY_FUNCTION__ << std::endl;
        if(m_data) {
            std::cout << " ~\"" << m_data << "\"" << std::endl;
            delete[] m_data;
        } // otherwise, this String was moved-from. Nothing to delete
    }
    template<size_t lenPlusOne>
    explicit String(const char (&x)[lenPlusOne]) {
         std::cout << __PRETTY_FUNCTION__ << std::endl;
         m_data = new char[lenPlusOne];
         strncpy(m_data, x, lenPlusOne);
         m_len = lenPlusOne - 1; // to deal with the trailing '\0'
         assert(m_data[m_len] == '\0');
    }
};


String returnsT() {
    std::cout << __PRETTY_FUNCTION__ << "    Inside returnsT().  It will do some stuff here." << std::endl;
    String s("returnsT");
    std::cout << __PRETTY_FUNCTION__ << "    Inside returnsT().  About to return." << std::endl;
    return s;
}

int main() {
    String s1("first");
    String s2("second");
    String s3("third");

    std::cout << std::endl;
    std::cout << " === Situation A): Assign from l-value. Copy required." << std::endl << std::endl;
    s1 = s2;

    {
    std::cout << std::endl;
    std::cout << " === Situation B): Assign from returnsT() returning T.  C++03 can optimize this, no copy *OR* move required after the return." << std::endl << std::endl;
    s1 = returnsT();
    }

    {
    std::cout << std::endl;
    std::cout << " === Situation C): Assign from move() returning T&&." << std::endl << std::endl;
    s1 =             std::move(s3) ;
    //s1 = StringRVRef(std::move(s3));
    }

    std::cout << std::endl;
    std::cout << " === Done. main() will finish now, destructing the three local strings." << std::endl << std::endl;
}
