Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous namespaces: Are they really that great?

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?

like image 228
Johan Kotlinski Avatar asked Dec 22 '10 21:12

Johan Kotlinski


2 Answers

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
}
like image 152
Steve Jessop Avatar answered Sep 22 '22 06:09

Steve Jessop


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.

like image 37
Martin Avatar answered Sep 22 '22 06:09

Martin