这是一个理论问题:假设您有一个库并且它有两个标题。是否有可能使用 C++ 或预处理器宏或两者的组合来实现以下行为:
- 依赖项目可以在任意数量的编译单元中包含 Header 1 或 Header 2 而不会出错。
- 依赖项目不能包含两个 header ,即使它跨不同的编译单元也是如此。
对于第二种情况,我想要一些会导致某种错误(例如链接器错误)的结构。我不需要给出一个很好的错误消息,我只是想禁止在同一个依赖项目中包含两个不兼容的头文件。这可能吗?
示例:
Header1.h
// type definitions for foo, Version 1
...
Header2.h
// type definitions for foo, Version 2
...
场景 1:
// (linker) error, versions do not match
CompilationUnit1.cpp <-- Header1.h
CompilationUnit2.cpp <-- Header2.h
场景 2:
// ok, versions match
CompilationUnit1.cpp <-- Header2.h
CompilationUnit2.cpp <-- Header2.h
最佳答案
您正在使用 Visual C++,然后它可以完成(但请注意,它不可移植,除非您使用 /WX
,否则您将收到警告而不是错误).使用 GCC(也许,我没试过)你可能会以某种方式使用 #pragma weak
。
因为每个编译单元都是单独编译的,所以您必须在链接器级别找到东西(导出函数,更改设置)。我发现最简单的方法是声明一个部分并在其上分配一个虚拟变量。如果此部分在您的 header 上声明为具有不同的属性,则链接器会提示。
您必须将此添加到 Header1.h:
#pragma section("mylib_priv_impl_section",read)
__declspec(allocate("mylib_priv_impl_section")) static int mylib_priv_impl_var = 0;
然后在Header2.h中:
#pragma section("mylib_priv_impl_section",read,write)
__declspec(allocate("mylib_priv_impl_section")) static int mylib_priv_impl_var = 0;
现在当你编译和链接时你会得到这个警告:
multiple 'mylib_priv_impl_section' sections found with different attributes (C0300040)
因为我们用不同的属性声明了相同的部分(read
在 Header1 和 read+write
在 Header2)。不幸的是,这只是一个警告(您可以使用部分名称来提供一些有用的诊断信息)并且要停止编译,您必须指定 /WX
(不幸的是被 #pragma comment(linker, "/WX ")
).
请注意,我们需要那个dummy 变量,否则我们声明的部分(如果未使用)将被简单地忽略。除了我们的虚拟变量外,其他什么都不会放在该部分(另请参见 Scope of __declspec allocations)。
请注意,如果预处理器宏可行,那么解决方案也类似于 Marco Giordano建议将工作顺利。如果您包含 Header1 但您设置要使用 Version2(反之亦然)而不是包含要包含的宏,我只是更改它抛出错误的工作方式。像这样的东西(在 Header1 中和 Header2 中的镜面反射):
#if MyLibVersion != 1
#error You are including version 1 headers, please set MyLibVersion accordingly.
#endif
关于c++ - 禁止跨编译单元包含不兼容的 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34924799/