类将自身传递给其他类的构造函数,两者都使用模板定义

Class passing itself to constructor of other class, both defined with templates

本文关键字:两者都 定义 构造函数 其他      更新时间:2023-10-16

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);
相关文章: