这是我的尝试:
template<class T>
class Child : public T
{
public:
typedef T Parent;
};
template<typename _T>
class has_parent
{
private:
typedef char One;
typedef struct { char array[2]; } Two;
template<typename _C>
static One test(typename _C::Parent *);
template<typename _C>
static Two test(...);
public:
enum { value = (sizeof(test<_T>(nullptr)) == sizeof(One)) };
};
class A
{
public :
virtual void print() = 0;
};
class B : public Child<A>
{
public:
void print() override
{
printf("toto \n");
}
};
template<class T, bool hasParent = has_parent<T>::value>
class ICovariantSharedPtr;
template<class T>
class ICovariantSharedPtr<T, true> : public ICovariantSharedPtr<typename T::Parent>
{
public:
T * get() override = 0;
};
template<class T>
class ICovariantSharedPtr<T, false>
{
public:
virtual T * get() = 0;
};
template<class T>
class CovariantSharedPtr : public ICovariantSharedPtr<T>
{
public:
CovariantSharedPtr(){}
CovariantSharedPtr(std::shared_ptr<T> a_ptr) : m_ptr(std::move(a_ptr)){}
T * get() final
{
return m_ptr.get();
}
private:
std::shared_ptr<T> m_ptr;
};
一个小例子:
class UseA
{
public:
virtual ICovariantSharedPtr<A> & GetPtr() = 0;
};
class UseB : public UseA
{
public:
CovariantSharedPtr<B> & GetPtr() final
{
return m_ptrB;
}
private:
CovariantSharedPtr<B> m_ptrB = std::make_shared<B>();
};
int _tmain(int argc, _TCHAR* argv[])
{
UseB b;
UseA & a = b;
a.GetPtr().get()->print();
}
解释:
这个解决方案涉及元编程和修改协变智能指针中使用的类。
简单的模板结构体 Child
用于绑定类型 Parent
和继承关系。任何从 Child<T>
继承的类都将从 T
继承并将 T
定义为 Parent
。协变智能指针中使用的类需要定义此类型。
类 has_parent
用于在编译时检测一个类是否定义了类型 Parent
。这部分不是我的,我使用了与检测方法是否存在相同的代码 (请看这里)
由于我们希望智能指针支持协变,我们希望我们的智能指针模仿现有的类架构。在示例中更容易解释它的工作原理。
当定义一个
CovariantSharedPtr<B>
时,它继承自
ICovariantSharedPtr<B>
,这被解释为
ICovariantSharedPtr<B, has_parent<B>::value>
。由于
B
继承自
Child<A>
,所以
has_parent<B>::value
为 true,因此
ICovariantSharedPtr<B>
是
ICovariantSharedPtr<B, true>
并继承自
ICovariantSharedPtr<B::Parent>
,即
ICovariantSharedPtr<A>
。由于
A
没有定义
Parent
,
has_parent<A>::value
为 false,
ICovariantSharedPtr<A>
是
ICovariantSharedPtr<A, false>
并且不继承任何内容。
重点在于B
从A
继承,因此我们有ICovariantSharedPtr<B>
从ICovariantSharedPtr<A>
继承。因此,任何返回ICovariantSharedPtr<A>
指针或引用的方法都可以被返回ICovariantSharedPtr<B>
的相同方法重载。
std::unique_ptr<Class>(obj.clone())
。 - quant_dev