Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

External linkage for name inside unnamed namespace

According to the clause 3.5/4 of C++ Standard:

An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage.

Simultanously in paragraph 7.3.1.1 we have note 96):

Although entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit.

How to explicitly make external linkage for name inside unnamed namespace and how to check that linkage is actually external if Standard guaranteed that there is no way to access name defined inside unnamed namespace from another translation unit?

In which cases doing explicit external linkage for name inside unnamed namespace is useful?

like image 322
αλεχολυτ Avatar asked Feb 09 '16 09:02

αλεχολυτ


People also ask

What is the use of unnamed namespace?

An anonymous namespace makes the enclosed variables, functions, classes, etc. available only inside that file. In your example it's a way to avoid global variables. There is no runtime or compile time performance difference.

Which identifier is used in a external link process?

External identifiers are the ones that are used in an external link process. These identifiers are also known as external names; include function names and global variable names that are shared between source files. The external identifier can be a name of the function or a global variable.

Which keyword is used for internal linkage?

To use internal linkage we have to use which keyword? Explanation: static keyword is used for internal linkage.

What is inline namespace in c++?

Prerequisite : Namespaces in C++ An inline namespace is a namespace that uses the optional keyword inline in its original-namespace-definition. CPP.


1 Answers

Re

In which cases doing explicit external linkage for name inside unnamed namespace is useful?

The need for external linkage was important for C++03 templates. E.g. a function pointer as template argument had to be a pointer to function of external linkage. For example, the following would not compile with a C++03 compiler:

template< void(*f)() >
void tfunc() { f(); }

#include <stdio.h>
static void g() { printf( "Hello!\n" ); }

int main()
{
    tfunc<g>();
}

It compiles fine with a C++11 compiler.

So, with C++11 the anonymous namespace mechanism for having external linkage yet no name conflicts between translation units, is only technically necessary for classes. A class has external linkage. One wouldn't want to have to choose class names that guaranteed did not occur in other translation units.

With C++11 the rules changed not only for template parameters, but for whether things in an anonymous namespace have external linkage or not. With C++03 an anonymous namespace had formally external linkage, possibly unless it is itself within an anonymous namespace (C++03 §3.5/4 last dash + C++03 §7.3.1.1/1). With C++11 an anonymous namespace has formally internal linkage.

This does not matter to the linker, because there's no linking of namespaces, but it matters as a formal device to describe linkage of things:

C++11 §3.5/4:

An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage. A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of
— a variable; or
— a function; or
— a named class (Clause 9), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes (7.1.3); or
— a named enumeration (7.2), or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes (7.1.3); or
— an enumerator belonging to an enumeration with linkage; or
— a template.


Before going on to your other questions, it's worth noting that this quote from the standard,

Although entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit.

is plain wrong, because an extern "C" entity is visible from other translation units regardless of what namespace it's declared in.

Happily, as I recall, notes are non-normative, i.e. they do not define the language.


Re

How to explicitly make external linkage for name inside unnamed namespace

just declare a non-const variable, or a function, as extern. you can declare a non-const variable, or a function, as extern "C", making the linkage extern but at the same time making the namespaces irrelevant as far as linking is concerned: the C language doesn't have them.

namespace {
    extern "C" void foo() {}    // Extern linkage
}  // namespace <anon>

void bar() {}  // Also extern linkage, but visible to other TUs.

Re

how to check that linkage is actually external

well, the linkage affects things like possible conflicts with the One Definition Rule, often abbreviated as the “ODR”, which in C++11 is §3.2.

So, one way to see the linkage in action is to link two object files generated from the above source, as if you had two translation units with that same source code:

C:\my\forums\so\088> g++ -c anon.cpp -o x.o & g++ -c anon.cpp -o y.o

C:\my\forums\so\088> g++ main.cpp x.o y.o
y.o:anon.cpp:(.text+0x0): multiple definition of `foo'
x.o:anon.cpp:(.text+0x0): first defined here
y.o:anon.cpp:(.text+0x7): multiple definition of `bar()'
x.o:anon.cpp:(.text+0x7): first defined here
collect2.exe: error: ld returned 1 exit status

C:\my\forums\so\088> _

The linker complains about multiple definitions of foo, because as with C language binding it appears, as far as the linker is concerned, as a non-inline external linkage member of the global namespace, with two (possibly conflicting) definitions.

like image 148
Cheers and hth. - Alf Avatar answered Sep 23 '22 06:09

Cheers and hth. - Alf