Note that there are some explanatory texts on larger screens.

plurals
  1. POC++ External Declaration Isolation
    primarykey
    data
    text
    <p>Consider the following:</p> <pre><code>namespace N { extern "C" void f(); } void g() { N::f(); } </code></pre> <p>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.</p> <p>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 <code>extern</code> 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.</p> <p><strong>Is it possible to do the same with functions or methods with regular C++ linkage?</strong> 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 <em>another</em> namespace?</p> <p>Intended functionality (pseudo-code):</p> <pre><code>namespace N { // Actually should link with P::f() (and not N::f()). extern "C++" void f(); } void g() { N::f(); // P::f(); } </code></pre> <p>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).</p> <p>Compiler-specific solutions are welcome (MSVC and GCC being of interest).</p> <p><strong>Example:</strong> suppose my library is called <code>Lib1</code> and I want to declare everything inside the <code>Lib1</code> namespace.</p> <pre><code>// Lib1.hpp namespace Lib1 { class Class1; void func1(); // ... } </code></pre> <p>Now suppose my library refers to another library, <code>Lib2</code>, which is a C library provided by someone else.</p> <pre><code>/* Lib2.h */ #ifdef __cplusplus extern "C" { #endif struct Struct2; void func2(); /* ... */ #ifdef __cplusplus } #endif </code></pre> <p>In my library, I can refer to entities from <code>Lib2</code> without having to include <code>Lib2.h</code> at all, if for some reason this is needed:</p> <pre><code>// Lib1.hpp namespace Lib1 { extern "C" void func2(); inline void inlineX() { func2(); } } </code></pre> <p>At the same time, a client code is free to include both <code>Lib1.hpp</code> and <code>Lib2.h</code> (considering it is C++-friendly) without conflicts.</p> <p>Now, suppose there is a third library, <code>Lib3</code>, which is a C++ library and declares entities in the <code>Lib3</code> namespace.</p> <pre><code>// Lib3.hpp namespace Lib3 { class Class3; void func3(); // ... } </code></pre> <p>Is there a way to relate to <code>Lib3</code> in the same manner as <code>Lib2</code>? That is: refer to entities in <code>Lib3</code> inside <code>Lib1.hpp</code>, without including <code>Lib3.hpp</code> but still allowing client code to include both <code>Lib1.hpp</code> and <code>Lib3.hpp</code> with no hassles?</p> <p>If, in <code>Lib1</code>, it is declared:</p> <pre><code>// Lib1.hpp namespace Lib3 { void func3(); } namespace Lib1 { inline void inlineY() { Lib3::func3(); } } </code></pre> <p>then it might occur conflicts if client code includes both <code>Lib1.hpp</code> and <code>Lib3.hpp</code> -- 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 <code>Lib1</code> namespace.</p> <p>Hope this helps to understand the question.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload