Consider the following:
namespace N {
extern "C" void f();
}
void g() {
N::f();
}
This code declares an external function with C linkage inside a namespace. This makes possible to refer to such a function from a private namespace, avoiding the resulting namespace pollution caused by an ordinary global external declaration. It also allows client code to issue other (hopefully compatible) declarations for the same function without conflicts, even in the global namespace, possibly originated from a vendor-provided header inclusion.
I often rely on similar constructs in both C and C++ to isolate compilations from bad-written or conflicting header files provided with some libraries. (In C, this is achieved by issuing the needed declarations at function scope, which would be also possible in C++, if not for the extern
linkage declaration being not allowed at function scope.) This is specially useful for properly linking against a well-defined ABI without having to rely on vendor-provided header files.
Is it possible to do the same with functions or methods with regular C++ linkage? That is: to declare an external function with C++ linkage inside a private namespace (or at any sort of local scope), but which possibly refers to a function actually defined inside another namespace?
Intended functionality (pseudo-code):
namespace N {
// Actually should link with P::f() (and not N::f()).
extern "C++" void f();
}
void g() {
N::f(); // P::f();
}
This obviously is not a problem for source files (as opposed to header files), because namespace pollution does not matter in that case. Thus, this question refers mostly to isolating declarations in library header files (for use inside templates and inline functions).
Compiler-specific solutions are welcome (MSVC and GCC being of interest).
Example: suppose my library is called Lib1
and I want to declare everything inside the Lib1
namespace.
// Lib1.hpp
namespace Lib1 {
class Class1;
void func1();
// ...
}
Now suppose my library refers to another library, Lib2
, which is a C library provided by someone else.
/* Lib2.h */
#ifdef __cplusplus
extern "C" {
#endif
struct Struct2;
void func2();
/* ... */
#ifdef __cplusplus
}
#endif
In my library, I can refer to entities from Lib2
without having to include Lib2.h
at all, if for some reason this is needed:
// Lib1.hpp
namespace Lib1 {
extern "C" void func2();
inline void inlineX() {
func2();
}
}
At the same time, a client code is free to include both Lib1.hpp
and Lib2.h
(considering it is C++-friendly) without conflicts.
Now, suppose there is a third library, Lib3
, which is a C++ library and declares entities in the Lib3
namespace.
// Lib3.hpp
namespace Lib3 {
class Class3;
void func3();
// ...
}
Is there a way to relate to Lib3
in the same manner as Lib2
? That is: refer to entities in Lib3
inside Lib1.hpp
, without including Lib3.hpp
but still allowing client code to include both Lib1.hpp
and Lib3.hpp
with no hassles?
If, in Lib1
, it is declared:
// Lib1.hpp
namespace Lib3 {
void func3();
}
namespace Lib1 {
inline void inlineY() {
Lib3::func3();
}
}
then it might occur conflicts if client code includes both Lib1.hpp
and Lib3.hpp
-- certainly not in this simple example in which the declarations are identical, but subtle differences in real situations can trigger warnings or errors at syntax level, even if the underlying ABI is the same, since this violates the premise of not declaring anything outside the Lib1
namespace.
Hope this helps to understand the question.
Isn't this just the intended usage of the using
directive in C++?
// Lib3.hpp
#pragma once
namespace Lib3 {
void func3();
}
// Lib1.hpp
#include <Lib3.hpp>
namespace Lib1 {
using Lib3::func3;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With