これが私の試みです:
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
。この部分は私のものではありません。メソッドが存在するかどうかを検出するのと同じコードを使用しました (こちらを参照) 。
スマート ポインターとの共分散が必要なため、スマート ポインターは既存のクラス アーキテクチャを模倣する必要があります。例でどのように機能するかを説明する方が簡単です。
aCovariantSharedPtr<B>
が定義されると、 から継承されICovariantSharedPtr<B>
、 として解釈されICovariantSharedPtr<B, has_parent<B>::value>
ます。As B
inherits from Child<A>
, has_parent<B>::value
is true, so ICovariantSharedPtr<B>
is ICovariantSharedPtr<B, true>
and inherits from ICovariantSharedPtr<B::Parent>
which is ICovariantSharedPtr<A>
. As A
has no Parent
defined, has_parent<A>::value
is false, ICovariantSharedPtr<A>
is ICovariantSharedPtr<A, false>
and inherits from nothing.
要点はB
から継承しA
ているように、からICovariantSharedPtr<B>
継承していICovariantSharedPtr<A>
ます。したがって、ポインタまたは参照をICovariantSharedPtr<A>
返すメソッドは、同じ on を返すメソッドによってオーバーロードできますICovariantSharedPtr<B>
。