Why an Unnamed Namespace Is a "Superior" Alternative to Static

Why an unnamed namespace is a superior alternative to static?

  • As you've mentioned, namespace works for anything, not just for functions and objects.
  • As Greg has pointed out, static means too many things already.
  • Namespaces provide a uniform and consistent way of controlling visibility at the global scope. You don't have to use different tools for the same thing.
  • When using an anonymous namespace, the function/object name will get mangled properly, which allows you to see something like "(anonymous namespace)::xyz" in the symbol table after de-mangling, and not just "xyz" with static linkage.
  • As pointed out in the comments below, it isn't allowed to use static things as template arguments, while with anonymous namespaces it's fine.
  • More? Probably, but I can't think of anything else right now.

Superiority of unnamed namespace over static?

You're basically referring to the section §7.3.1.1/2 from the C++03 Standard,

The use of the static keyword is
deprecated when declaring objects in a
namespace scope; the
unnamed-namespace provides a superior
alternative.

Note that this paragraph was already removed in C++11. static functions are per standard no longer deprecated!

Nonetheless, unnamed namespace's are superior to the static keyword, primarily because the keyword static applies only to the variables declarations and functions, not to the user-defined types.

The following code is valid in C++:

//legal code
static int sample_function() { /* function body */ }
static int sample_variable;

But this code is NOT valid:

//illegal code
static class sample_class { /* class body */ };
static struct sample_struct { /* struct body */ };

So the solution is, unnamed (aka anonymous) namespace, which is this:

//legal code
namespace
{
class sample_class { /* class body */ };
struct sample_struct { /* struct body */ };
}

Hope it explains that why unnamed namespace is superior to static.


Also, note that use of static keyword is deprecated when declaring objects in a namespace scope (as per the Standard).

Why are anonymous namespaces not a sufficient replacement for namespace-static, according to the standards committee?

This is a more in-depth explanation.

Although 7.3.1.1 [namespace.unnamed] states that the use of the static keyword for declaring variables in namespace scope is deprecated because the unnamed namespace provides a superior alternative, it is unlikely that the feature will be removed at any point in the foreseeable future, especially in light of C compatibility concerns. The Committee should consider removing the deprecation.

One issue I know is that anonymous namespaces can't specialize templates outside of the namespace block. This is why inline namespace was introduced, although static works too. Also, static plays much nice with macros.

Unnamed/anonymous namespaces vs. static functions

The C++ Standard reads in section 7.3.1.1 Unnamed namespaces, paragraph 2:

The use of the static keyword is
deprecated when declaring objects in a
namespace scope, the unnamed-namespace
provides a superior alternative.

Static only applies to names of objects, functions, and anonymous unions, not to type declarations.

Edit:

The decision to deprecate this use of the static keyword (affecting visibility of a variable declaration in a translation unit) has been reversed (ref). In this case using a static or an unnamed namespace are back to being essentially two ways of doing the exact same thing. For more discussion please see this SO question.

Unnamed namespace's still have the advantage of allowing you to define translation-unit-local types. Please see this SO question for more details.

Credit goes to Mike Percy for bringing this to my attention.

Why are anonymous namespaces preferred to static globals?

Static variables at namespace scope are no longer deprecated.

There's no particular reason to prefer one over the other. A minor reason to prefer an unnamed namespace is that you can declare anything inside it, while only functions and variables can be static. A minor reason to prefer static declarations is that you don't have extra braces loitering around the declaration. Use whichever feels more harmonious to you.

Historical note: before C++11, there was one reason to prefer a namespace: for some bizarre reason, pointers to static objects or functions could not be used as template arguments, while pointers to non-static ones could. C++11 removes this restriction, along with the equally odd restrictions preventing, for example, local types being template arguments.

Why are unnamed namespaces used and what are their benefits?

Unnamed namespaces are a utility to make an identifier translation unit local. They behave as if you would choose a unique name per translation unit for a namespace:

namespace unique { /* empty */ }
using namespace unique;
namespace unique { /* namespace body. stuff in here */ }

The extra step using the empty body is important, so you can already refer within the namespace body to identifiers like ::name that are defined in that namespace, since the using directive already took place.

This means you can have free functions called (for example) help that can exist in multiple translation units, and they won't clash at link time. The effect is almost identical to using the static keyword used in C which you can put in in the declaration of identifiers. Unnamed namespaces are a superior alternative, being able to even make a type translation unit local.

namespace { int a1; }
static int a2;

Both a's are translation unit local and won't clash at link time. But the difference is that the a1 in the anonymous namespace gets a unique name.

Read the excellent article at comeau-computing Why is an unnamed namespace used instead of static? (Archive.org mirror).

Why should types be put in unnamed namespaces?

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.

unnamed namespace

What does it exactly mean?

Technically deprecated means that a future standard may remove the feature.

In practice that isn't going to happen, because of the need to support old code.

So in practice it means, "strongly discouraged".

Example of superiority of unnamed namespace

An unnamed namespace is generally superior because what you have in that namespace can have external linkage.

In C++98 external linkage is necessary for things that can be template parameters, e.g., if you want to templatize on a char const*, it must be pointer to char that has external linkage.

#include <iostream>

// Compile with "-D LINKAGE=static" to see problem with "static"
#ifndef LINKAGE
# define LINKAGE extern
#endif

template< char const* s >
void foo()
{
std::cout << s << std::endl;
}

namespace {
LINKAGE char const message[] = "Hello, world!";
} // namespace anon

int main()
{
foo<message>();
}

That said, it's a bit inconsistent that static isn't also deprecated for functions.

Are objects in anonymous namespace implicitly static?

C++11, 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 ...

So in C++11 both of your foo objects have internal linkage. In C++03, the first one has external linkage.

Regardless of linkage, it has static storage duration.

I don't think there's any such thing in the standard as "take the object as if it was marked static", so I can't answer to that. If you find some text in the standard that refers to whether the object is "marked static" and doesn't refer specifically to either linkage or storage duration, then cite it and I can give you an opinion :-)



Related Topics



Leave a reply



Submit