Superiority of Unnamed Namespace Over Static

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 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.

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.

Are static or unnamed namespace still useful when header and implementation are separated?

Keeping a definition in implementation file does not make it private in any sense. Any other header or implementation file can declare that function and use it. It's not always a bad thing - I used parts of private implementations of libraries when I really needed it (but I do not recommend doing that).

The worse part of having such not-so-private implementation is its potential for One Definition Rule violation. ODR states that every* function or variable must have exactly one definition in the whole program. If there is more than one definition, behaviour is undefined**.

This means that when you have your not-so-private implementation in your file and nobody knows about it, they can unknowingly write a function with the same name and arguments and get an ODR violation.

It would be a good practice to use static or anonymous namespace for all free functions that should be limited to a single file. Functions that need to be used from other files cannot use this strategy, so to limit the risk of ODR violations you should use descriptive names and perhaps (named) namespaces. Just make sure you don't overuse namespaces.


Note: using anonymous namespaces doesn't make sense in header files. Anonymous namespace limits the scope of its content to the translation unit in which it exists, but header files are copied and pasted into (potentially) multiple TUs. The one use of anonymous namespaces is in header-only libraries, as described in this question - it allows to create global objects in header file without ODR violation (but at a cost that each TU has its own copy of that variable).


*except for template functions, inline functions, functions defined in class definition and a couple more. Even then, all definitions must be exactly the same.

**When I encountered it once, linker used random definition, whichever it saw at that moment. Hilarity and long debugging sessions ensued.

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.

Unnecessary use of unnamed namespaces C++

In this particular case, the namespace is indeed redundant, because the const namespace scope variables indeed have internal linkage by default.

Consider the possibility of changing the code later. Perhaps one of the variables shouldn't be const after all. But making it non-const also changes the default linkage. The anonymous namespace would keep the internal linkage even after such change. In other words, the anon namespace separates the concerns over constness and the linkage. Whether that's a good thing, depends on the context.

Note that same thing can be achieved by using static keyword. Since this has exactly the same effect as the anon namespace, the choice is mostly aesthetic and therefore opinion based.

An argument for using anon namespaces instead of static could be consistency. You cannot define types with internal linkage with static. Since some internal symbols (types) cannot be defined outside an anonymous namespace, you could have a convention to define all internal symbols in an anonymous namespace. Of course, such convention would be - as conventions typically are - a matter of taste.

Your second counter argument seems to be arguing against a difference that doesn't exist. The anonymous namespace makes no difference to name hiding within function scope.

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.

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).

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.



Related Topics



Leave a reply



Submit