请看以下内容:
这显然不是源文件(区别于头文件)的问题,因为在这种情况下命名空间污染并不重要。 因此,这个问题主要涉及隔离库头文件中的声明(用于模板和内联函数)。
欢迎使用特定于编译器的解决方案(MSVC和GCC受到关注)。
例如:假设我的库名为“Lib1”,我想在“Lib1”命名空间中声明所有内容。
在我的库中,如果需要的话,我可以引用来自
有没有一种方法可以像处理
如果在
如果客户端代码同时包含
namespace N {
extern "C" void f();
}
void g() {
N::f();
}
这段代码在命名空间内声明了一个具有C语言链接的外部函数。这使得可以从私有命名空间中引用这样的函数,避免普通全局外部声明所造成的命名空间污染。它还允许客户端代码发出其他(希望兼容的)对同一函数的声明而不会冲突,即使是来自供应商提供的头文件包含的全局命名空间。
我经常在C和C++中依赖类似的结构来隔离编译与一些库提供的糟糕或冲突的头文件。 (在C中,通过在函数范围内发出所需的声明来实现此目的,如果不是因为不允许在函数范围内进行extern链接声明,则在C ++中也可能实现。)这对于正确链接到定义良好的ABI特别有用,而无需依赖供应商提供的头文件。
是否可以使用具有常规C ++链接的函数或方法执行相同操作?也就是说:在私有命名空间(或任何类型的本地作用域)中声明具有C ++链接的外部函数,但其可能引用实际在另一个命名空间中定义的函数?
预期功能(伪代码):
namespace N {
// Actually should link with P::f() (and not N::f()).
extern "C++" void f();
}
void g() {
N::f(); // P::f();
}
这显然不是源文件(区别于头文件)的问题,因为在这种情况下命名空间污染并不重要。 因此,这个问题主要涉及隔离库头文件中的声明(用于模板和内联函数)。
欢迎使用特定于编译器的解决方案(MSVC和GCC受到关注)。
例如:假设我的库名为“Lib1”,我想在“Lib1”命名空间中声明所有内容。
// Lib1.hpp
namespace Lib1 {
class Class1;
void func1();
// ...
}
现在假设我的库引用了另一个库Lib2
,这是由其他人提供的C库。
/* Lib2.h */
#ifdef __cplusplus
extern "C" {
#endif
struct Struct2;
void func2();
/* ... */
#ifdef __cplusplus
}
#endif
在我的库中,如果需要的话,我可以引用来自
Lib2
的实体而无需包含Lib2.h
:// Lib1.hpp
namespace Lib1 {
extern "C" void func2();
inline void inlineX() {
func2();
}
}
同时,客户端代码可以自由地包含Lib1.hpp
和Lib2.h
(如果符合C++友好性),而不会发生冲突。
现在,假设有第三个库Lib3
,它是一个C++库,并在Lib3
命名空间中声明实体。
// Lib3.hpp
namespace Lib3 {
class Class3;
void func3();
// ...
}
有没有一种方法可以像处理
Lib2
那样处理Lib3
?也就是说,在不包括Lib3.hpp
的情况下,在Lib1.hpp
中引用Lib3
的实体,但仍允许客户端代码无需麻烦地包括Lib1.hpp
和Lib3.hpp
。如果在
Lib1
中声明:// Lib1.hpp
namespace Lib3 {
void func3();
}
namespace Lib1 {
inline void inlineY() {
Lib3::func3();
}
}
如果客户端代码同时包含
Lib1.hpp
和Lib3.hpp
,就可能发生冲突--当然,在这个简单的示例中声明是相同的,但是在实际情况下微小的差异可以触发语法级别的警告或错误,即使底层ABI相同,因为这违反了不在Lib1
命名空间之外声明任何内容的前提条件。希望这能帮助理解问题。
N
来表示P
呢?为什么不直接写P
呢? - Igor Tandetnikextern "C"
会导致一个带有C名称混淆的符号(没有命名空间!)。因此,保护只会在您的代码内部生效。 - dornhege