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
C++ #Include <Atlbase.H> Is Not Found
C++ Object Size with Virtual Methods
Why Should the Assignment Operator Return a Reference to the Object
How to Delete a Non-New Object
What Does '<Cuchar>' Provide, and Where Is It Documented
Does Static Constexpr Variable Inside a Function Make Sense
Very Poor Boost::Lexical_Cast Performance
Use Wm_Copydata to Send Data Between Processes
How to Filter Items from a Std::Map
Emulating Shifts on 32 Bytes with Avx
How to Declare a Vector of Atomic in C++
How to Get the CPU Usage Per Thread on Windows (Win32)
Does the Gotw #101 "Solution" Actually Solve Anything
Changing the Value of Const Variable in C++
What Does {0} Mean When Initializing an Object