如果我的理解是正确的,下面是模板类之间的经典循环依赖:
template <class MyB>
struct A {
MyB *b_;
};
template <class MyA>
struct B {
MyA *a_;
};
如果我们要实例化A
与 B
和 B
与 A
, 那么我们不能从任何一个开始,因为我们必须写:A<B<A<B<...>>>
(无限)。
我认为模板模板参数提供了一种解决方案。以下代码编译(使用 gcc
版本 4.8.2):
template <class MyB>
struct A {
MyB *b_;
};
template <template <class> class MyA>
struct B {
MyA<B> *a_;
};
int main() {
using MyB = B<A>;
using MyA = A<MyB>;
MyA a;
MyB b;
a.b_ = &b; b.a_ = &a;
return 0;
}
我是否遗漏了问题的本质?
更新:我刚遇到 this帖子提出了基本相同的解决方案。
最佳答案
我会尝试设计我的代码以避免那些循环依赖。无论如何,如果有令人信服的理由不这样做,有几种方法可以解决这个问题:
如您所述,使用模板模板参数通过打破循环来解决问题
template <class MyB> struct A { MyB *b_; }; template <template <class> class MyA> struct B { MyA<B> *a_; }; int main() { using MyB = B<A>; using MyA = A<MyB>; MyA a; MyB b; a.b_ = &b; b.a_ = &a; return 0; }
另一种解决方案是将您需要的类型封装到外部结构/类中
template<class Common> struct A { typedef typename Common::BT B; B* b; }; template<class Common> struct B { typedef typename Common::AT A; A* a; }; struct Common { using AT = A<Common>; using BT = B<Common>; }; int main() { A<Common> a; B<Common> b; return 0; }
根据其余代码的作用,在像这样的简单情况下,您可能会使用可变参数模板
template <class MyA> struct B; template <typename ...MyB> struct A { B<A<>> *b_; }; template <> struct A<> {}; template <class MyA> struct B { A<B<MyA>> *a_; }; int main() { using BoA = B<A<>>; using AoBoA = A<B<A<>>>; BoA obj1; AoBoA obj2; obj1.a_ = &obj2; obj2.b_ = &obj1; return 0; }
最后值得注意的是公开一个公共(public)基类并使用 CRTP -like 方法可能是实现这一目标的更简洁的方法(您甚至可能因清晰度和可读性而获得分数)。
关于c++ - 使用模板模板参数打破模板循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34128529/