16

I have been using the static keyword a long time for defining internal linkage. Later, I switched to the C++ style of wrapping local things in anonymous namespaces.

However, now when I have worked with anonymous namespaces for some years, I start to think that static keyword is a lot easier to work with!

A common problem is that I have this pattern:

namespace {
    // ...five pages of code...
}  // namespace

To see if a certain function has internal or external linkage, I now have to scroll a lot, as opposed to the old C style where I could just check if the function/object had static in front of it.

I know there are things anonymous namespaces do that static can't - hide typedefs - but personally I'm not really very interested in that, anyway.

What are your take on this? Is the win of anonymous namespaces that great that it warrants the decreased readability? Or am I all out wrong?

Johan Kotlinski
  • 25,185
  • 9
  • 78
  • 101
  • 3
    `static` functions in namespace scope have been deprecated, that's sufficient reason not to use them. Functions in anon namespace have all advantages of `static`, except they have external linkage. The latter I think is already taken care of by compilers, removing names defined in anonymous namespaces from exported section. – Gene Bushuyev Dec 22 '10 at 21:58
  • 11
    @Gene actually, static functions were never deprecated. The deprecation was only against *objects*. However, the deprecation was removed in n3225: In C++0x it's not deprecated anymore to use it to give objects or functions internal linkage. Another difference fallen over is that unnamed namespaces would retain external linkage: Unnamed namespaces and their content will get internal linkage in C++0x. So there doesn't seem to be any difference anymore between the static-way and the namespace-way, except the namespace-way will allow things like `namespace { int a; } int a;`. – Johannes Schaub - litb Dec 22 '10 at 22:09
  • @Johannes: does C++0x allow template parameters with internal linkage, or is that a honking great breaking change? – Steve Jessop Dec 22 '10 at 22:15
  • @Steve yes it allows template arguments to have internal linkage. – Johannes Schaub - litb Dec 22 '10 at 22:20
  • possible duplicate of [Superiority of unnamed namespace over static ?](http://stackoverflow.com/questions/4422507/superiority-of-unnamed-namespace-over-static) – Ben Voigt Dec 22 '10 at 22:34
  • @Ben: It may be a duplicate, but this question has better answers :) – Johan Kotlinski Dec 22 '10 at 22:51

3 Answers3

20

If the code in your namespace is too long, there's nothing to stop you doing this:

namespace {
    int foo(char* x) {
        return x[0] + x[1];
    }
}

namespace {
    int bar(char *x, char *y) {
        return foo(x) + foo(y);
    }
}

In C++03 the practical advantage of using an unnamed namespace is precisely that the contents have external linkage, (but are still invisible outside the TU because there's no way to refer to them). Template parameters can't have internal linkage:

namespace {
    int foo(const char* x) {
        return x[0] + x[1];
    }
}

static int foo2(const char *x) {
    return x[0] + x[1];
}

template <int (*F)(const char*)>
void baz(const char *p) {
    F(p);
}

int main() {
    baz<foo>("ab");   // OK
    baz<foo2>("ab");  // not valid
}
Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • Yes, but is that really making things better? More typing, more parentheses to balance... – Johan Kotlinski Dec 22 '10 at 22:04
  • 4
    @kotlinksi: Well, you're the one who said it was a readability problem that you've only typed `namespace {}` once in several screens of code. Now you're saying it's a writability problem to type it more than once. If you can manage using functions with internal linkage then you can use `static`. If for some reason you need functions with external linkage, then it doesn't really matter what the advantages of `static` are, because you can't have them. – Steve Jessop Dec 22 '10 at 22:11
  • @kotlinksy: I suppose another possibility would be to create a header file just for these functions. Give it a name that indicates all its contents are in the unnamed namespace, and then you can tell where the functions are by what file they're in. – Steve Jessop Dec 22 '10 at 22:20
3

Apart from the very valid points noted by Steve I see other very important aspects in anonymous namespaces that make them superior to static functions: Locality, ease of refactoring and information hiding.

Assume you have one or two class function that require several other helper functions which are quite specific but do not use class members. If you stick with Robert C. Martin (Functions should be small and serve one well defined purpose) you will often find that large functions can be refactored into smaller ones although these smaller ones might in the beginning only be used in the former big function.

So what Options do you have:

  1. Make a new (perhaps private) class immediately:

    This entails quite a lot of typing might be overkill and -lets face it- everybody is sometimes lazy or in a hurry.

  2. Generate private static functions or non-member functions:

    Both entails editing the header file and the cpp file if you do it properly, so still a little burden that might interrupt your workflow more than necessary and generates code that unnecessarily clutters your header file, might necessitate forward declarations or even additional includes in your header.

  3. Anonymous namespace:

    You have a helper function that does not need member access and serves one purpose -> Put it there and write this function close to the class methods where it will be used. This is by large my preferred one:It's quick and it does not clutter the header file. The namespace clearly states: this is not used by anything else than this cpp. No friend will use it and no library user will ever know it's existence. You can hardly be more obvious and often this paradigm will lead to cleaner function design which is few input parameters and only one output modified. Further you have function locality: Define just before primary use. While this might be a drawback I find it quite help ful when browsing the implementations of large classes. Another advantage is constants that span several functions but are not really interesting for a library user. Put them in the namespace as well, best in the same with the functions that use them. If it turns out later that you need the constants and the functions elsewhere, transform the whole into a class, its already neatly packed.

Disclaimer: Many people might argue that the use of a pimpl is by far cleaner. This is just my personal opinion.

Martin
  • 4,738
  • 4
  • 28
  • 57
2

An anonymous namespace is the only thing that does not let a class declaration pollute the global scope. Very useful when defining a class in a .cpp file.

Thomas Eding
  • 35,312
  • 13
  • 75
  • 106