I just made a wrapper for move and copy operations to inject into code to see which is called in case of default implementations. I'm getting close to understanding when what is called but would like to double check at times.
I'm not sure if method 1 of using T::T;
is better for the constructors than method 2 of forwarding the arguments like unique_ptr? I found it in this thread Forwarding all constructors in C++0x
In move constructor and assignment I use std::move
to pass onto the super class. Should this be std::forward
and if so, how? I get errors trying to use it.
#ifndef MOVECOPY_OBSERVER_H
#define MOVECOPY_OBSERVER_H
#include <iostream>
template<class T>
class MoveCopyObserver : public T {
public:
//1: Use "using" for constructors
//From https://stackoverflow.com/questions/3119929/forwarding-all-constructors-in-c0x
using T::T;
//2: Forward all args, unique_ptr style.
/*
template<typename... Args>
MoveCopyObserver(Args&&... args)
: T(std::forward<Args>(args)...)
{
};*/
// *************************************************************************
virtual ~MoveCopyObserver() = default;
// *************************************************************************
MoveCopyObserver(const MoveCopyObserver& other)
: T(other)
{
std::cout << "Copy constructor " << typeid(T).name() << std::endl;
}
// *************************************************************************
MoveCopyObserver(MoveCopyObserver && other)
: T(std::move(other)) //3: std::forward instead?
{
std::cout << "Move constructor " << typeid(T).name() << std::endl;
}
// *************************************************************************
MoveCopyObserver& operator=(const MoveCopyObserver& other)
{
T::operator=(other);
std::cout << "Copy assignment " << typeid(T).name() << std::endl;
return *this;
}
// *************************************************************************
MoveCopyObserver& operator=(MoveCopyObserver&& other)
{
T::operator=(std::move(other)); //3: std::forward instead?
std::cout << "Move assignment " << typeid(T).name() << std::endl;
return *this;
}
};
#endif //MOVECOPY_OBSERVER_H
The usage would be on the stack or through smart pointers, like so:
class A {
public:
A(std::string ss)
{
s = ss;
}
void f()
{
std::cout << "\"" << s << "\"" << std::endl;
}
private:
std::string s;
};
A a("Test instance");
a.foo();
MoveCopyObserver<A> b("Another instance");
b.foo();