How it works...

When a function is declared in a translation unit, it has external linkage. That means two functions with the same name from two different translation units would generate a linkage error because it is not possible to have two symbols with the same name. The way this problem is solved in C, and by some in C++ also, is to declare the function or variable static and change its linkage from external to internal. In this case, its name is no longer exported outside the translation unit, and the linkage problem is avoided.

The proper solution in C++ is to use unnamed namespaces. When you define a namespace like the ones shown above, the compiler transforms it to the following:

    // file1.cpp 
namespace _unique_name_ {}
using namespace _unique_name_;
namespace _unique_name_
{
void print(std::string message)
{
std::cout << "[file1] " << message << std::endl;
}
}

void file1_run()
{
print("run");
}

First of all, it declares a namespace with a unique name (what the name is and how it generates that name is a compiler implementation detail and should not be a concern). At this point, the namespace is empty, and the purpose of this line is to basically establish the namespace. Second, a using directive brings everything from the _unique_name_ namespace into the current namespace. Third, the namespace, with the compiler-generated name, is defined as it was in the original source code (when it had no name).

By defining the translation unit local print() functions in an unnamed namespace, they have local visibility only, yet their external linkage no longer produces linkage errors since they now have external unique names.

Unnamed namespaces are also working in a perhaps more obscure situation involving templates. Prior to C++11 template non-type arguments could not be names with internal linkage so using static variables was not possible. On the other hand, symbols in an unnamed namespace have external linkage and could be used as template arguments. Although this linkage restriction for template non-type arguments was lifted in C++11, it is still present in the latest version of the VC++ compiler. This problem is shown in the following example where declaring t1 produces a compiler error, because the non-type argument expression has internal linkage, but t2 is correct because Size2 has external linkage. (Note that compiling the code below with Clang and gcc do not produce any error.)

    template <int const& Size> 
class test {};

static int Size1 = 10;

namespace
{
int Size2 = 10;
}

test<Size1> t1;
test<Size2> t2;
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset