如何在C++中声明/定义相互依赖的模板?
How to declare/define interdependent templates in C++?
通常在C++中,当我需要类之间的相互依赖关系时,我在头文件中使用前向声明,然后在每个 cpp 文件中包含两个头文件。
但是,此方法在使用模板时会中断。因为模板必须完全在头文件中(不包括我将代码放入 cpp 并为每个支持的T
枚举template class A<T>;
的情况 - 这并不总是可行的,例如当T
是 lambda 时(。
那么有没有办法在C++中声明/定义相互依赖的模板呢?
代码示例
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
}
};
如果我开始做一些事情来B
RunA()
,我想,我会得到一个"缺少定义"错误,因为在编译时只有 B 的前向声明可用RunA()
。
也许有一些技巧来组织头文件,例如将每个头文件拆分为类定义和方法定义文件,然后以某种花哨的方式包含它们。或者也许可以通过第三/第四类来完成一些事情。但我无法想象具体如何做到这一点。
C++11/14/17 没问题(具体来说,它是 MSVC++2017,工具集 v141(。
您可以使用细粒度标头:
// 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"
显然,所有这些标头也需要我在此处省略的某种标头保护。重要提示:.impl.hpp
标头被视为内部标头,不应由外部代码使用,而.forward.hpp
、.decl.hpp
和.hpp
可以在任何地方使用。
这种方法确实引入了循环包含依赖项,但这不会导致问题:通过包含标头生成的代码结构可确保代码部分按以下顺序包含:前向声明、类定义、方法定义。
可以分隔类的声明和定义。因此,您可以分离模板类的声明和定义...
可以分隔类方法的声明和定义。因此,您可以分离模板类方法的声明和定义:
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
}
相关文章:
- 为什么即使直到最后才定义实际类型,也可以将依赖名称视为完整
- (Wix 安装程序)如何包含自定义操作依赖项
- 如何定义依赖于参数包转换的函数的返回类型
- FBString 的小字符串优化是否依赖于未定义的行为?
- 错误 LNK1104:错误消息中显示的路径未在其他依赖项中定义
- 循环依赖结构,使用前向声明时结构的错误重定义
- 使用 libpthread 在共享库中未定义的行为,但不将其作为依赖项在 ELF 中
- 如何在C++中声明/定义相互依赖的模板?
- 继承依赖类型定义而不使用结构
- g++ 生成依赖项文件缺少用户定义的标头
- 单独库中的类成员函数定义和链接依赖项
- 如何转发声明依赖于变量定义的类,而变体定义又依赖于模板化类?
- 如何打破定义嵌套模板类的标头的圆形依赖关系
- 如何定义具有依赖于符号调试的参数的函数
- Visual Studio:用户依赖定义
- 依赖GCC/LLVM的"-fexceptions"在技术上是未定义的行为吗?
- gmp 的 libgmp.so 有哪些依赖关系?我不断收到未定义的引用
- 如何从同一个头文件中定义 2 个类,而一个类依赖于另一个类
- 使用定义相互依赖
- 循环依赖(类对类型定义,类型定义对类),前向声明给出不明确的调用