7

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.

Wake up Brazil
  • 3,421
  • 12
  • 19
  • 2
    I suspect the footnote may be a leftover from C++03, where names in unnamed namespaces had external linkage (because otherwise they couldn't be used as template parameters). The authors simply forgot to remove it. – Igor Tandetnik Sep 25 '14 at 01:00

3 Answers3

5

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.

T.C.
  • 133,968
  • 17
  • 288
  • 421
1

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?

Community
  • 1
  • 1
Praxeolitic
  • 22,455
  • 16
  • 75
  • 126
  • AFAIK you have proved that unnamed namespace had external linkage in C++03, and for that matter you don't even need the declaration `extern int i;`, as the compiler recognizes the declaration `int i = 5;` as having external linkage. – Wake up Brazil Sep 25 '14 at 12:53
  • For C++11 I can only quote to you the standard, but since you already provide the relevant quote in the OP, it's unclear what you're looking for. Does it help to know that a namespace and the variables within do not necessarily have the same linkage? – Praxeolitic Sep 25 '14 at 12:59
  • Also, what changed in C++11 that breaks the example is template parameters, not linkage rules. – Praxeolitic Sep 25 '14 at 13:20
  • In C++11 the code compiles because the declaration `extern int i;` doesn't add anything to the declaration `int i = 5;`, i.e., the variable `i` continues to have internal linkage, despite the `extern` specifier. – Wake up Brazil Sep 25 '14 at 14:04
0

For example

#include <iostream>

namespace
{
    extern int x = 10;

    void f( int y )
    {
        extern int x;
        std::cout << x + y << std::endl;
    }
}

int main() 
{
    int y =  15;

    f( y );

    return 0;
}

According to the C++ Standard

6 The name of a function declared in block scope and the name of a variable declared by a block scope extern declaration have linkage. If there is a visible declaration of an entity with linkage having the same name and type, ignoring entities declared outside the innermost enclosing namespace scope, the block scope declaration declares that same entity and receives the linkage of the previous declaration. If there is more than one such matching entity, the program is ill-formed. Otherwise, if no matching entity is found, the block scope entity receives external linkage

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I believe the `or` in §3.5/2 first bullet point is not exclusive. So, I don't agree that `x` has external linkage in your example. – Wake up Brazil Sep 24 '14 at 21:46
  • @Wake up Brazil x Os automatica variable that is declared with quakifier extern. So if there is preceding declaration of x in the enclosing namespace with linkage then x has the same linkage.See 3.5/6. – Vlad from Moscow Sep 25 '14 at 03:40
  • §3.5/6 just tells you that the local `x` has the same linkage as the `x` declared in namespace scope `extern int x = 10;`. But that doesn't imply that this `x` has external linkage. See §3.5/4 first bullet point: `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;`. See also §7.1.1/6 that refers to §3.5, regarding the linkage of a name declared with the `extern` specifier. – Wake up Brazil Sep 25 '14 at 13:54
  • @Wake up Brazil it seems you do not understand what you read. Variable x is defined as having external linkage in an unnamed namespace. The local variable declaed in the function has also external linkage because there is a variable with the same name and linkage in the enclosing namespace. What is the problem?!. – Vlad from Moscow Sep 25 '14 at 17:09