2015-12-07 3 views
4

Если я правильно понимаю, следующая классическая циклическая зависимость между классами шаблона:Ломая шаблон круговой зависимости с помощью шаблона параметров шаблона

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, в котором предлагается практически то же решение.

ответ

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; 
    } 
    
  • Другое решение может быть инкапсулировать тип нужно во внешние структуры/классе

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

Наконец, стоит отметить, что выставляя общий базовый класс и используя CRTP -как подход, вероятно, может быть чище путь для достижения этого (вы даже можете получить очки для ясности и удобочитаемости).

Смежные вопросы