7

I have been reading articles about unnamed namespaces the whole day, most articles explained when you should use unnamed namespaces over the static keyword. But I am still left with one big question when is it appropriate to use static? After all it is not completely deprecated, what about header files with static functions should I put them into unnamed namespaces now?

#ifndef HEADER_H
#define HEADER_H

static int func() {
  ...
}

// versus:

namespace {
  int func() {
    ...
  }
};

#endif // HEADER_H 

Or what about static member functions?

Greetings

Dummy00001
  • 16,630
  • 5
  • 41
  • 63
haribo
  • 71
  • 2
  • 7
    Seems counter productive to put static (or unnamed namsepaces) in header files. If they are static why are they not just in the source file? – Martin York Oct 08 '10 at 17:15

4 Answers4

5

The precise wording of the standard is:

The use of the static keyword is deprecated when declaring objects in namespace scope.

Functions in a header file should be inline rather than static or in an unnamed namespace. inline means you will only end up with at most one copy of the function in your program, while the other methods will give you a separate copy from each file that includes the header. As well as bloat, this could give incorrect behaviour if the function contains function-static data. (EDIT: unless the function is supposed to have different definitions in different compilation units, perhaps due to different preprocessor macros that are defined before including the header file. In that case the best approach is not to include it at all, but rather to bury it in an unmarked grave with a stake through its unholy heart.)

Data objects, apart from constants, usually shouldn't be defined in header files at all, only declared extern.

Static member functions are a different kettle of fish, and you have to use static there as there is no other way to declare them. That usage isn't deprecated, since it isn't in namespace scope.

UPDATE: C++11 has removed the deprecation, so there's no longer any particular reason to prefer unnamed namespaces over static. But you still shouldn't use either in a header file unless you're doing something weird.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • "Data objects shouldn't be defined in header files at all, only declared extern if they need external linkage." This is imprecise. "Data object", as you call them, have external linkage by default, unless they're const. So extern is needed to make their declaration just a declaration and not a definition, which is the default. However if both extern and an initializer are present, it is a definition. – Armen Tsirunyan Oct 08 '10 at 14:18
  • Data objects often need to be defined in header files. That includes constants (which are objects). I guess it's good advice for C++ novices to avoid defining (static class member) constants of non-integral types in header files. More experienced programmers can do that using e.g. the templated constants trick. Another such trick is a function returning a reference to a local static constant. – Cheers and hth. - Alf Oct 08 '10 at 14:24
  • @Armen, @Alf: yes, my advice concerning data objects was a bit simplistic. I'll rephrase it. – Mike Seymour Oct 08 '10 at 14:31
  • 1
    OK, good explanation for external and static member functions. Concerning inline I always thought it would replace the function calls with the function code itself and thus I end up with a lot of copies?! – haribo Oct 08 '10 at 14:31
  • @haribo: The definition of an inline function is allowed and REQUIRED in all the translation units in which the function is used. So it's a great way to make sure you won't get linker errors when you define a function in a .h file (note that when a member function is defined lexically INSIDE the class, it is implicitly inline). The replacing of the function calls with the code itself is an optional thing which the comiler can choose to do or ignore. – Armen Tsirunyan Oct 08 '10 at 14:34
  • @haribo: on most compilers, `inline` will make no difference to whether a function gets inlined or not; you can end up with multiple (inlined) copies of any function that the compiler decides to inline. The purpose of `inline` is to give the function inline linkage; this means that you are allowed identical definitions in multiple compilation units, and only one copy ends up in the final program. Using `static` or an nameless namespace will give identical definitions of *different* functions, all of which will end up in the final program. – Mike Seymour Oct 08 '10 at 14:42
  • @Mike: regarding inline. Better make sure that all definitions of the function (across the various objects) is the same, because of ODR the linker will probably never bother to check and just assume so. – Matthieu M. Oct 08 '10 at 18:14
  • @Matthieu: good point; I've added my opinion of header file functions that might differ between compilation units. – Mike Seymour Oct 08 '10 at 22:54
  • 4
    "or in an unnamed namespace." - nooo that's utterly bad. Unnamed namespaces are for .cpp files that want to make data, functions or types TU-local. So that they can use common names and are guaranteed to not conflict. But if you place them into the header, you pollute that private environment! – Johannes Schaub - litb Oct 09 '10 at 08:45
  • The deprecation of using `static` at namespace scope has been removed in C++11. The standard no longer encourages use of `unnamed namespace` over `static`. – Alok Save Jan 06 '12 at 18:23
3

There is no advantage of static in namespace scope over unnamed namespaces which I know of. Use unnamed namespaces, as in the example above. Actually in the example above I can't see why is static or unnamed namespace necessary. Maybe inline? And static member functions have nothing to do with static at namespace scope. Static member functions (and nonfunction members) are still valid.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • In the example the static is needed in order to avoid the function having external linkage. As it will be implemented in every module that uses the header, the linker might object if the static keyword is not present. – Alexander Rautenberg Oct 08 '10 at 14:11
  • @Alexander: Well, inline will allow multiple definitions of the function. And in my opinion is a superior alternative. However, if "INTERNAL LINKAGE" is exactly what is needed, then unnamed namespace is much better, at least because it is not deprecated. – Armen Tsirunyan Oct 08 '10 at 14:15
  • 4
    `inline` allows multiple *identical* definitions of the function. `static` allows multiple different definitions, since each translation unit has its own function with internal linkage, they just happen to be referred to by the same name. So, if there's something in the definition of `func` that depends on some #defines (such as `assert`), and you want it to be legal to combine different TUs that included the header with different values in the #define, then you'd need either `static` or an unnamed namespace. `inline` won't do, officially, although in practice it might work. – Steve Jessop Oct 08 '10 at 15:19
  • If _internal linkage_ is **exactly** what is required then an unnamed namespace is not sufficient. While it may be a technicality, members of an unnamed namespace (other than other namespaces) have _external linkage_ by default. – CB Bailey Oct 08 '10 at 23:10
  • My FCD says "Although entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit." – Ben Voigt Oct 09 '10 at 00:10
3

In a header file there's usually no point in specifying internal linkage, or using an anonymous namespace.

In a separately compiled implementation file you can use static or an anonymous namespace to avoid linkage level name collisions or client code relying on implementation details. An anonymous namespace lets you have external linkage, which is required for template parameters, and it also supports class definitions. But in the end it's just a question of practicality and personal preference, on a case by case basis.

static for a member function has nothing to do with linkage specification. A static member function has external linkage anyway.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
0

static can be preferable if you are using some tools. It also behaves a bit better with auto indent functionality in most text editors. It's a bit sad, when you have to avoid using something useful because it doesn't work with tools that should really support it, but I promise you'll get over it.

An example question that gives some hint of potential pain in the debugging department:

Viewing namespaced global variables in Visual Studio debugger?

You probably won't have to look very hard to find more problems, but the debugger issues were enough to make me entirely give up on namespaces, to the maximum extent possible, so I've never looked any further.

My personal recommendation is that for code that will be around for less than forever, one might as well go with static. Does effectively the same thing as an unnamed namespace, but, averaged out over all tools, it is better supported. In theory, one day it will disappear completely, but I'm happy to publicly admit that I'm certain that day will never actually come to pass. And in the mean time, you are saving yourself some pain.

Community
  • 1
  • 1