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; };

据我所知,这工作正常(在程序的其余部分中使用specAspecB)。但是,以下内容不起作用(丢失的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);

08-24 19:19