#include <iostream>
#include <utility>
#include <string>
class Var
{
private:
struct controlBlockBase
{
unsigned short uses;
controlBlockBase() : uses(1) { }
virtual ~controlBlockBase() { }
};
template <class K>
struct controlBlockImpl : controlBlockBase
{
K value;
controlBlockImpl(const K &val) : controlBlockBase(), value(val) {}
};
controlBlockBase *cb;
public:
Var() : cb(nullptr) {
std::cout << "Var default constructed" << std::endl;
}
template<typename K>
Var(const K &value) : cb(new controlBlockImpl<K>(value)) {
std::cout << "Var value constructed" << std::endl;
}
Var(const Var &obj) : cb(obj.cb) {
if (cb) {
++(cb->uses);
}
std::cout << "Var copy constructed" << std::endl;
}
Var(Var &&obj) : cb(nullptr) {
obj.swap(*this);
std::cout << "Var move constructed" << std::endl;
}
~Var() {
if ((cb) && ((cb->uses -= 1) <= 0)) {
delete cb;
cb = nullptr;
}
std::cout << "Var destructed" << std::endl;
}
Var& operator=(const Var& obj) {
if (this != &obj) {
Var(obj).swap(*this);
}
std::cout << "Var copy assigned" << std::endl;
return *this;
}
Var& operator=(Var &&obj) {
obj.swap(*this);
std::cout << "Var move assigned" << std::endl;
return *this;
}
void swap(Var &other) {
std::swap(cb, other.cb);
}
unsigned short getUses() const {
return (cb) ? cb->uses : 0;
}
};
namespace std {
void swap(Var &v1, Var &v2) {
v1.swap(v2);
}
}
class C
{
public:
Var var;
C() {
std::cout << "C default constructed" << std::endl;
}
C(const C &c) : var(c.var) {
std::cout << "C copy constructed" << std::endl;
}
C(C &&c) : var(std::move(c.var)) {
std::cout << "C move constructed" << std::endl;
}
C(Var var) : var(var) {
std::cout << "C value constructed" << std::endl;
}
~C() {
std::cout << "C destructed" << std::endl;
}
C& operator=(const C &c) {
if (this != &c) {
C tmp(c);
std::swap(var, tmp.var);
}
std::cout << "C copy assigned" << std::endl;
return *this;
}
C& operator=(C &&c) {
std::swap(var, c.var);
std::cout << "C move assigned" << std::endl;
return *this;
}
};
class MyString
{
public:
std::string str;
MyString() {
std::cout << "MyString default constructed" << std::endl;
}
MyString(const char *s) : str(s) {
std::cout << "MyString value constructed" << std::endl;
}
MyString(const std::string &s) : str(s) {
std::cout << "MyString value constructed" << std::endl;
}
MyString(const MyString &s) : str(s.str) {
std::cout << "MyString copy constructed" << std::endl;
}
MyString(MyString &&s) : str(std::move(s.str)) {
std::cout << "MyString move constructed" << std::endl;
}
~MyString() {
std::cout << "MyString destructed" << std::endl;
}
MyString& operator=(const MyString &s) {
if (this != &s) {
str = s.str;
}
std::cout << "MyString copy assigned" << std::endl;
return *this;
}
MyString& operator=(MyString &&s) {
str = std::move(s.str);
std::cout << "MyString move assigned" << std::endl;
return *this;
}
};
void test()
{
MyString string = "Hello";
Var var1 = Var(string);
std::cout << "var1 uses=" << var1.getUses() << std::endl;
C c = C(var1);
std::cout << "var1 uses=" << var1.getUses() << std::endl;
Var var2 = Var(c);
std::cout << "var1 uses=" << var1.getUses() << std::endl;
std::cout << "var2 uses=" << var2.getUses() << std::endl;
}
int main() {
test();
return 0;
}