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.