Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Example of entity declared in a anonymous namespace that has external linkage

Given the statements below (emphasis mine) in §3.5/4 and in the Note [94] in §7.3.1.1/1, I'd like to have one single example of an entity declared in a unnamed namespace that has external linkage.

§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.

Note [94] on §7.3.1.1/1:

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.

like image 391
Wake up Brazil Avatar asked Sep 24 '14 20:09

Wake up Brazil


People also ask

What is external linkage?

The term external linkage means that a symbol in one translation unit can be accessed from other translation units, whereas exporting refers to a symbol that is visible from a library file such as a DLL. Only external linkage symbols can be exported.

What are anonymous namespaces?

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.

Are variables in anonymous namespace static?

Theoretically, extern variables declared in anonymous namespace is a superior alternative over a simple static variable. That's why the "static global variables" were deprecated before C++11.

Do entities in an unnamed namespace have external linkage?

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.

What is internal and external linkage in C++?

With C++11 an anonymous namespace has formally internal linkage. ” An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage.

Does the declaration of an externally linked identifier take up any space?

Thus, the declaration of an externally linked identifier does not take up any space. Extern identifiers are generally stored in initialized/uninitialized or text segment of RAM. Please do go through Understanding extern keyword in C before proceeding to the following examples. It is possible to use an extern variable in a local scope.

How does the keyword extern implement external linkage?

The keyword extern implements external linkage. When we use the keyword extern, we tell the linker to look for the definition elsewhere. Thus, the declaration of an externally linked identifier does not take up any space.


2 Answers

You are looking at a defect in the standard.

The change that makes unnamed namespace members have internal linkage happened fairly late in the C++11 standardization process, in November 2010 (CWG issue 1113). As a result, a number of places in the standard needs to be changed, but weren't. One of which is the footnote you quoted.

CWG issue 1603, currently in "ready" status (read: the resolution is likely to be adopted at the next committee meeting), will fix this and a number of other issues related to giving internal linkage to unnamed namespace members.

like image 53
T.C. Avatar answered Oct 19 '22 23:10

T.C.


It's a good question because it's difficult to demonstrate. We can take advantage of other rules in the C++ Standard to show that a variable in an anonymous namespace can have external linkage.

Templating on an int* with external linkage will succeed while templating on an int* with internal linkage will fail.

#include <iostream>

namespace {
    // not externally linked, won't compile
    // const int i = 5;

    // external linkage, compiles
    extern int i;
    int i = 5;
}

template<int* int_ptr>
struct temp_on_extern_linked_int {
    temp_on_extern_linked_int() {
        std::cout << *int_ptr << std::endl;
    }
};

int main() {
    temp_on_extern_linked_int<&i>();
}

As shown the program compiles and runs.

$ g++-4.8 main.cpp -o main
$ ./main
5

Uncommenting the other definition of i causes the compile to fail.

$ g++-4.8 main.cpp -o main
main.cpp: In function 'int main()':
main.cpp:17:30: error: '& {anonymous}::i' is not a valid template argument of
type 'int*' because '{anonymous}::i' does not have external linkage
  temp_on_extern_linked_int<&i>();
                              ^

The compiler is quite helpful. It explicitly states that because i doesn't have external linkage the compile failed.

The commented definition of i has internal linkage because it is qualified const without extern. (§3.4.6)

Variables at namespace scope that are declared const and not extern have internal linkage.

Part of the trick is not compiling as C++11.

Why did C++03 require template parameters to have external linkage?

like image 39
Praxeolitic Avatar answered Oct 19 '22 23:10

Praxeolitic