How to declare/define interdependent templates in C++?

偶尔善良 提交于 2020-01-10 04:33:08

问题


Usually in C++ when I need interdependencies between classes, I use forward declarations in the header files and then include both header files in each cpp file.

However this approach breaks when working with templates. Because templates have to be entirely in the header files (not counting the case when I put the code into cpp and enumerate template class A<T>; for each supported T - this is not always feasible, e.g. when T is a lambda).

So is there a way to declare/define interdependent templates in C++?

Code example

template<typename T> struct B;
template<typename T> struct A {
  void RunA(B<T> *pB) {
    // need to do something to B here
  }
};

template<typename T> struct B {
  void RunB(A<T> *pA) {
    // need to do something to A here
  }
};

If I start doing something to B in RunA(), I think, I will get a "missing definition" error because only forward declaration of B is available by the time RunA() is compiled.

Perhaps there is some trick to organize header files e.g. by splitting each header into class definition and method definition files, and then including them in some fancy way. Or maybe something can be done via a third/fourth class. But I can't imagine how specifically to do this.

C++11/14/17 are ok (specifically, it's MSVC++2017, toolset v141).


回答1:


You can utilize fine-grained headers:

//  A.forward.hpp
template<typename T> struct A;

//  A.decl.hpp
#include "A.forward.hpp"
#include "B.forward.hpp"

template<typename T> struct A
{
    void RunA(B<T> *pB);
};

//  A.impl.hpp
#include "A.decl.hpp"
#include "B.hpp"

template<typename T> void A< T >::
RunA(B<T> *pB)
{
    // need to do something to B here
}

//  A.hpp // this one should be included by code using A
#include "A.decl.hpp"
#include "A.impl.hpp"

//  B.forward.hpp
template<typename T> struct B;

//  B.decl.hpp
#include "B.forward.hpp"
#include "A.forward.hpp"

template<typename T> struct B
{
    void RunB(A<T> *pA);
};

//  B.impl.hpp
#include "B.decl.hpp"
#include "A.hpp"

template<typename T> void B< T >::
RunB(A<T> *pA)
{
    // need to do something to A here
}

//  B.hpp // this one should be included by code using B
#include "B.decl.hpp"
#include "B.impl.hpp"

Obviously all of these headers also need some sort of header guards that I omitted here. Important notice: .impl.hpp headers are considered internal and should never be used by the outside code while .forward.hpp, .decl.hpp and .hpp can be used anywhere.

This approach does introduce circular include dependencies, however this does not lead to problems: code structure produced by inclusion of headers ensures that code parts are included in the following order: forward declarations, class definitions, methods definitions.




回答2:


You can separate the declarations and definitions of classes. Therefore you can separate the declarations and definitions of template classes...

You can separate the declarations and definitions of class methods. Therefore you can separate the declarations and definitions of template class methods:

template<typename T> struct B;     // declaration

template<typename T> struct A {     // definition
  void RunA(B<T> *pB);  // declaration
};

template<typename T> struct B {     // definition
  void RunB(A<T> *pA);   // declaration
};

// definition
template<typename T>
void A<T>::RunA(B<T> *pB) {
    // need to do something to B here
  }

// definition    
template<typename T>
void B<T>::RunB(A<T> *pA) {
    // need to do something to A here
  }


来源:https://stackoverflow.com/questions/45402913/how-to-declare-define-interdependent-templates-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!