循环依赖(typedef上的类,类上的typedef),前向声明给出了不明智的调用?

时间:2018-01-09 10:46:07

标签: c++

我试图找到一个可接受的解决方案来解决以下循环依赖:

template<typename T>
struct Y {
  void f(T&) {}
};

template<typename T, typename U>
struct X : public Y<T>, public Y<U> {};

struct A;
struct B;
typedef X<A,B> Z;

struct A {
  void g(Z& z) {
    z.f(*this);
  }
};

struct B {
  void g(Z& z) {
    z.f(*this);
  }
};

int main(int argc, char** argv) {
  Z z;
  A a;
  B b;
  a.g(z);
  b.g(z);
}

代码Z取决于A和B,A / B取决于Z.A / B无法转换为模板类定义。当我转发声明A和B时(如图所示)然后我得到一个不明智的调用,大概是因为typedef用不完整的类型实例化X?

当然,我可以简单地将X定义为以下内容,一切正常:

struct A;
struct B;

struct X {
  void f(A&) {}
  void f(B&) {}
};

typedef X Z;

struct A {
  void g(Z& z) {
    z.f(*this);
  }
};

struct B {
  void g(Z& z) {
    z.f(*this);
  }
};

int main(int argc, char** argv) {
  Z z;
  A a;
  B b;
  a.g(z);
  b.g(z);
}

...但是当X是模板时如何将Z定义为typedef?

3 个答案:

答案 0 :(得分:5)

不,这不是因为类型不完整。在使用该成员之前,不会实例化成员函数定义。成员的声明将,但是不完整的类型不会使声明格式不正确。更不用说,你不会以任何方式使用该类型,因为它不完整。

这只是名称查找规则的一个人工制品。您可以提供使用声明,将f成员拉入X

template<typename T, typename U>
struct X : public Y<T>, public Y<U> {
    using Y<T>::f;
    using Y<U>::f;
};

这解决了歧义。

答案 1 :(得分:2)

这与循环依赖关系无关,但具有多重继承。铿锵的错误很明显:&#34;错误:会员&#39; f&#39;在多个不同类型的基类中找到&#34;。

一种解决方案是消除歧义f您的意思:是继承自Y<T>还是继承自Y<U>的人:

z.Y<A>::f(*this);

z.Y<B>::f(*this);

答案 2 :(得分:1)

我认为另一个解决方案是合理的,但有点难看的是:

template<typename T>
struct Y {
  void f(T&) {}
};

template<typename T, typename U>
struct X : public Y<T>, public Y<U> {
  template<typename V>
  void f(V& v) {
    this->Y<V>::f(v);
  }
};

struct A;
struct B;
typedef X<A,B> Z;

struct A {
  void g(Z& z) {
    z.f(*this);
  }
};

struct B {
  void g(Z& z) {
    z.f(*this);
  }
};

int main(int argc, char** argv) {
  Z z;
  A a;
  B b;
  a.g(z);
  b.g(z);
}