I am a newbie in C++ and have the following doubt concerning the Rule of Zero: can we use a deep-copy smart pointer compatible with polymorphism as a member-variable of a class without the need to declare any of the special member-functions (i.e. relying only on synthesized)???
For example, the following code surprisingly appears to work:
#include <iostream>
#include <cassert>
using namespace std;
template<typename Value>
struct Inteligent
{
private:
template <typename OtherValue>
friend struct Inteligent;
Value* pointer;
public:
Inteligent():pointer{nullptr}
{
creator=&create<Value>;
}
template<typename OtherValue>
Inteligent (const OtherValue& other)
{
creator=&create<OtherValue>;
pointer=creator(other);
}
Inteligent (const Inteligent& other)
{
creator=other.creator;
pointer=creator(*(other.pointer));
}
Inteligent (Inteligent&& other):pointer(other.pointer),creator(other.creator)
{
other.pointer=nullptr;
}
template<typename OtherValue>
Inteligent (const Inteligent<OtherValue>& other)
{
creator=other.creator;
pointer=creator(*(other.pointer));
}
template<typename OtherValue>
Inteligent (Inteligent<OtherValue>&& other):pointer(other.pointer),creator(other.creator)
{
other.pointer=nullptr;
}
template<typename OtherValue>
Inteligent&
operator= (const Inteligent<OtherValue>& other)
{
if(&other!=this)
{
delete pointer;
creator=other.creator;
pointer=creator(*(other.pointer));
}
return *this;
}
Inteligent&
operator= (const Inteligent& other)
{
if(&other!=this)
{
delete pointer;
creator=other.creator;
pointer=creator(*(other.pointer));
}
return *this;
}
template<typename OtherValue>
Inteligent&
operator= (Inteligent<OtherValue>&& other)
{
if(&other!=this)
{
delete pointer;
creator=other.creator;
pointer=other.pointer;
other.pointer=nullptr;
}
return *this;
}
Inteligent&
operator= (const Value& other)
{
if (pointer)
{
*pointer=other;
}
else
{
pointer=creator(other) ;
}
return *this;
}
~Inteligent()
{
delete pointer;
pointer=0;
}
Value&
operator()()
{
assert (pointer);
return *pointer;
}
const Value&
operator()() const
{
assert (pointer);
return *pointer;
}
operator Value& ()
{
assert (pointer);
return *pointer;
}
operator const Value& () const
{
assert (pointer);
return *pointer;
}
template<typename OtherValue>
OtherValue& as()
{
return (OtherValue&) this->operator()();
}
template<typename OtherValue>
const OtherValue& as() const
{
return (OtherValue&) this->operator()();
}
operator bool () const
{
return pointer;
}
private:
template<typename OtherValue>
static Value * create(const Value& arg)
{
return new OtherValue((OtherValue&)arg);
}
typedef Value* (*CREATION)(const Value& arg);
CREATION creator=nullptr;
public:
template<typename OtherValue,typename ...Arguments>
static Inteligent makeInteligent (const Arguments& ... arguments)
{
return Inteligent (OtherValue (arguments ...));
}
};
struct Base
{
int a;
virtual void speak()
{
cout<<"Base"<<endl;
cout<<"a="<<a<<endl;
}
};
struct Derivated:Base
{
int b;
void speak()
{
cout<<"Derivated"<<endl;
cout<<"a="<<a<<" e b="<<b<<endl;
}
};
struct Polimorfic
{
enum derivateds
{
base,
derivated
};
Inteligent<Base> ibase;
Polimorfic(const derivateds& temp)
{
switch (temp)
{
case base:
ibase=Inteligent<Base>::makeInteligent<Base>();
break;
case derivated:
ibase=Inteligent<Base>::makeInteligent<Derivated>();
break;
}
}
Base& obtain()
{
return ibase.operator ()();
}
Inteligent<Base>& inteligente()
{
return ibase;
}
};
int main()
{
Polimorfic p1(Polimorfic::base);
Polimorfic p2(Polimorfic::derivated);
p1.obtain().a=10;
p2.obtain().a=20;
p2.ibase.as<Derivated>().b=30;
p1.obtain().speak();
p2.obtain().speak();
p1=p2;
p1.obtain().speak();
p2.obtain().a=33;
p1.obtain().speak();
p2.obtain().speak();
return 0;
}
Why? Is the rule-of-zero just this? Am I missing something?
Aucun commentaire:
Enregistrer un commentaire