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 Binherits from A, we have ICovariantSharedPtrinheriting from ICovariantSharedPtr. So any method returning a pointer or a reference on ICovariantSharedPtr can be overloaded by a method returning the same on ICovariantSharedPtr.