Search code examples
c++c++11language-lawyermove-semanticsconst-reference

How to define move assignment operator for const ref member of template class


I have the following template class, where the member is const ref type. Copying of object is disabled and wanted to only have move cntor and move assignment operator.

Q1: How to implement move assignment operator for const ref type properly(Is it correct, what I made)?

Q2: Why this

MyClass<int> obj2(std::move(obj));   // will work with move ctor
MyClass<int> obj3 = std::move(obj2); // also move ctor called: Why?

happened?

Q3: In main() moved instances are able to called using print(). Is it UB?

I am using Visual Studio 2015 (v140). Here is my Code:

#include <utility>
#include <iostream>

template<typename Type>
class MyClass
{
    const Type& m_ref;  // const ref type
public:
    explicit MyClass(const Type& arg): m_ref(std::move(arg)){}

    // coping is not allowed
    MyClass(const MyClass&) = delete;
    MyClass& operator=(const MyClass&) = delete;

    // enables move semantics
    MyClass(MyClass &&other) : m_ref(std::move(other.m_ref)) { std::cout << "Move Cotr...\n"; } // works

    // how would I do the move assignment operator, properly: following?
    MyClass& operator=(MyClass &&other)
    {
        // this should have been done in initilizer list(due to const ref member), 
        // but here we cannnot and still it gives no errors, why?

        this->m_ref = std::move(other.m_ref);  
        std::cout << "Move =operator...\n";
        return *this;
    }

    // print the member
    const void print()const noexcept { std::cout << m_ref << std::endl; }
};

//test program
int main() {
    MyClass<int> obj(2);
    MyClass<int> obj2(std::move(obj));   // will work with move ctor
    MyClass<int> obj3 = std::move(obj2); // also move ctor called: Why?

    obj.print();  // why this prints 2? : is it UB?
    obj2.print(); // why this prints 2? : is it UB?
    obj3.print(); // here it makes sence.

    std::cin.get();
}

Solution

  • The first:

    MyClass<int> obj2(std::move(obj));   // will work with move ctor
    

    is direct initialization.

    The second:

    MyClass<int> obj3 = std::move(obj2); // also move ctor called: Why?
    

    is copy initialization.

    Both are constructing objects (obj2 and obj3 respectively) and initialize them. The = doesn't mean assignment in this context.