c++ - 使用模板模板参数打破模板循环依赖

标签 c++ templates

如果我的理解是正确的,下面是模板类之间的经典循环依赖:

template <class MyB>
struct A {
    MyB *b_;
};

template <class MyA>
struct B {
    MyA *a_;
};

如果我们要实例化ABBA , 那么我们不能从任何一个开始,因为我们必须写: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/

相关文章:

C++ 线性搜索算法

c++ - C++11强制无条件移动吗?

C++ 元编程 : Generating a byte sequence based on type/value input?

c++ - 模板中的非模板静态计数器

c++ - 模板类中的模板友元函数

c++ - 为什么隐式转换不应用于模板化函数参数?

c++ - 为什么 typedef struct 会产生链接失败

c++ - 如何限制用户输入的时间?

c++ - 无法匹配重载的运算符

C++:如何从 make_shared 部分推导模板参数