A
类(或其专长)应创建B
类(或其专长)的实例,后者具有一个字段来了解谁创建了它。以下代码可以解决问题:
template <typename R>
class A {
public:
R make() { return R(this); }
};
template <typename S>
class B {
public:
S * s;
B(S * s_) : s(s_) { }
};
挑战在于模板参数的循环依赖性。一种解决方案带有前向声明:
class specB;
typedef A<specB> specA;
class specB : public B<specA> { using B::B; };
据我所知,这工作正常(在程序的其余部分中使用
specA
和specB
)。但是,以下内容不起作用(丢失的using
不负责任,上面我只是为了找到B
的扩展构造函数而将其包括在内):class specA;
typedef B<specA> specB;
class specA : public A<specB> { };
它给:
In instantiation of ‘R A<R>::make() [with R = B<specA>]’:
required from here
error: invalid conversion from ‘A<B<specA> >* const’ to ‘specA*’ [-fpermissive]
R make() { return R(this); }
^
error: initializing argument 1 of ‘B<S>::B(S*) [with S = specA]’ [-fpermissive]
B(S * s_) : s(s_) { }
^
是否有可能使它也以这种方式工作(没有
-fpermissive
)?更新:这是一个可能的解决方案(似乎可以正常工作),但对我来说不合适:
template <typename S>
class B {
public:
S * s;
B(void * s_) : s(static_cast<S*>(s_)) { }
};
最佳答案
当通过派生类调用基类的方法时,该方法将this
作为指向基类的指针。基类的实现无法知道从基类派生的类。
在第二个示例中,创建了一个class A<B<specA>>
,并且一个类specA
继承了它。当您调用specA.make()
时,它将调用B<specA>(this)
,而this
的类型为A<B<specA>>*
。编译器抱怨B<specA>
的构造函数需要specA*
类型的参数。从基类指针到派生类指针没有微不足道的转换。
您可以这样操作:
template<typename T>
class Alloc
{
public:
T make() { return T(*this); }
};
template<template<typename> class A>
class Type
{
private:
A<Type>* a_;
public:
Type(A<Type>& a): a_(&a) { }
};
Alloc<Type<Alloc>> a;
Type<Alloc> t(a);