简体   繁体   中英

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.

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.

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM