Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why should types be put in unnamed namespaces?

I understand the use of unnamed namespaces to make functions and variables have internal linkage. Unnamed namespaces are not used in header files; only source files. Types declared in a source file cannot be used outside. So what's the use of putting types in unnamed namespaces?

See these links where it's mentioned that types can be put in unnamed namespaces:

  • Superiority of unnamed namespace over static?
  • Unnamed/anonymous namespaces vs. static functions
  • Why an unnamed namespace is a "superior" alternative to static?
like image 802
Francis Xavier Avatar asked Aug 19 '15 17:08

Francis Xavier


People also ask

Why do we use unnamed namespace?

Unnamed Namespaces They are directly usable in the same program and are used for declaring unique identifiers.

What does anonymous namespace mean?

November 19, 2020. Anonymous namespaces in C++ allow you to define locally-visible-only artifacts in C++. the static keyword provides equivalent (depending on C++ version) locally-visible-only variables and functions. //impl.cpp. //neither can be used externally.

Is unnamed namespace global?

The point of an unnamed namespace is to provide a unique namespace within a translation unit (= a source file) without requiring an explicit prefix. This allows you to guarantee that your global names won't clash with other, equal global names in other translation units.

When should namespaces be used?

Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries. All identifiers at namespace scope are visible to one another without qualification.


Video Answer


2 Answers

Where do you want to put local types other than the unnamed namespace? Types can't have a linkage specifier like static. If they are not publicly known, e.g., because they are declared in a header, there is a fair chance that names of local types conflict, e.g., when two translation units define types with the same name. In that case you'd end up with an ODR violation. Defining the types inside an unnamed namespace eliminates this possibility.

To be a bit more concrete. Consider you have

// file demo.h
int foo();
double bar();

// file foo.cpp
struct helper { int i; };
int foo() { helper h{}; return h.i; }

// file bar.cpp
struct helper { double d; }
double bar() { helper h{}; return h.d; }

// file main.cpp
#include "demo.h"
int main() {
     return foo() + bar();
}

If you link these three translation units, you have mismatching definitions of helper from foo.cpp and bar.cpp. The compiler/linker is not required to detect these but each type which is used in the program needs to have a consistent definition. Violating this constraints is known as violation of the "one definition rule" (ODR). Any violation of the ODR rule results in undefined behavior.

Given the comment it seems a bit more convincing is needed. The relevant section of the standard is 3.2 [basic.def.odr] paragraph 6:

There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then each definition of D shall consist of the same sequence of tokens; and [...]

There are plenty of further constraints but "shall consist of the same sequence of tokens" is clearly sufficient to rule out e.g. the definitions in the demo above from being legal.

like image 77
Dietmar Kühl Avatar answered Oct 20 '22 01:10

Dietmar Kühl


So what's the use of putting types in unnamed namespaces?

You can create short, meaningful classes with names that maybe used in more than one file without the problem of name conflicts.

For example, I use two classes often in unnamed namespaces - Initializer and Helper.

namespace
{
   struct Initializer
   {
      Initializer()
      {
         // Take care of things that need to be initialized at static
         // initialization time.
      }
   };

   struct Helper
   {
      // Provide functions that are useful for the implementation
      // but not exposed to the users of the main interface.
   };

   // Take care of things that need to be initialized at static
   // initialization time.
   Initializer initializer;
}

I can repeat this pattern of code in as many files as I want without the names Initializer and Helper getting in the way.

Update, in response to comment by OP

file-1.cpp:

struct Initializer
{
   Initializer();
};

Initializer::Initializer()
{
}

int main()
{
   Initializer init;
}

file-2.cpp:

struct Initializer
{
   Initializer();
};

Initializer::Initializer()
{
}

Command to build:

g++ file-1.cpp file-2.cpp

I get linker error message about multiple definitions of Initializer::Initializer(). Please note that the standard does not require the linker to produce this error. From section 3.2/4:

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.

The linker does not produce an error if the functions are defined inline:

struct Initializer
{
   Initializer() {}
};

That's OK for a simple case like this since the implementations are identical. If the inline implementations are different, the program is subject to undefined behavior.

like image 35
R Sahu Avatar answered Oct 20 '22 00:10

R Sahu