I have code like this:
class RetInterface {...}
class Ret1: public RetInterface {...}
class AInterface
{
public:
virtual boost::shared_ptr
Here is my attempt :
template
class Child : public T
{
public:
typedef T Parent;
};
template
class has_parent
{
private:
typedef char One;
typedef struct { char array[2]; } Two;
template
static One test(typename _C::Parent *);
template
static Two test(...);
public:
enum { value = (sizeof(test<_T>(nullptr)) == sizeof(One)) };
};
class A
{
public :
virtual void print() = 0;
};
class B : public Child
{
public:
void print() override
{
printf("toto \n");
}
};
template::value>
class ICovariantSharedPtr;
template
class ICovariantSharedPtr : public ICovariantSharedPtr
{
public:
T * get() override = 0;
};
template
class ICovariantSharedPtr
{
public:
virtual T * get() = 0;
};
template
class CovariantSharedPtr : public ICovariantSharedPtr
{
public:
CovariantSharedPtr(){}
CovariantSharedPtr(std::shared_ptr a_ptr) : m_ptr(std::move(a_ptr)){}
T * get() final
{
return m_ptr.get();
}
private:
std::shared_ptr m_ptr;
};
And a little example :
class UseA
{
public:
virtual ICovariantSharedPtr & GetPtr() = 0;
};
class UseB : public UseA
{
public:
CovariantSharedPtr & GetPtr() final
{
return m_ptrB;
}
private:
CovariantSharedPtr m_ptrB = std::make_shared();
};
int _tmain(int argc, _TCHAR* argv[])
{
UseB b;
UseA & a = b;
a.GetPtr().get()->print();
}
Explanations :
This solution implies meta-progamming and to modify the classes used in covariant smart pointers.
The simple template struct Child
is here to bind the type Parent
and inheritance. Any class inheriting from Child
will inherit from T
and define T
as Parent
. The classes used in covariant smart pointers needs this type to be defined.
The class has_parent
is used to detect at compile time if a class defines the type Parent
or not. This part is not mine, I used the same code as to detect if a method exists (see here)
As we want covariance with smart pointers, we want our smart pointers to mimic the existing class architecture. It's easier to explain how it works in the example.
When a CovariantSharedPtr
is defined, it inherits from ICovariantSharedPtr
, which is interpreted as ICovariantSharedPtr::value>
. As B
inherits from Child
, has_parent::value
is true, so ICovariantSharedPtr
is ICovariantSharedPtr
and inherits from ICovariantSharedPtr
which is ICovariantSharedPtr
. As A
has no Parent
defined, has_parent::value
is false, ICovariantSharedPtr
is ICovariantSharedPtr
and inherits from nothing.
The main point is as B
inherits from A
, we have ICovariantSharedPtr
inheriting from ICovariantSharedPtr
. So any method returning a pointer or a reference on ICovariantSharedPtr
can be overloaded by a method returning the same on ICovariantSharedPtr
.