foonathan::blog()

Thoughts from a C++ library developer.

One of C++ most underrated features: Namespace aliases

About two months ago I wrote the following r/cpp comment:

In the thread a new library was presented. One user complained about the long namespace name, (s)he got the above replies. Judging by the number of upvotes, people seemed to agree with my comment. In this blog post I am going to elaborate it.

But first, let me tell you a little story about me.


Advertisement

About naming things

I’m a library author.

As such, I write code that will be integrated into code written by others; the functions and classes I write will live in co-existence with the functions and classes written by my users. Obviously, they can only co-exist if their names are different. Thus I have to name my symbols in such a way that they will not conflict with any other possible symbol name; I don’t even know the names since I don’t know where my code will finally end up.

Luckily, this problem can be solved very easily in C++ and most other higher-level languages. They provide a way to put things into namespaces to avoid name collisions. Then you only have to come up with a namespace name - often the library name itself, put everything into that namespace and you never need to worry about naming issues ever again!

Except for macros. They suck.

Well, that’s the theory. In practice we - or at least I - run into one of the fundamental problems of CS:


I’m a library author.

I’m horrible at coming up with names.

In my defense: naming things is hard, okay? A name needs to be rather short yet unique in the scope - namespace(!) - of the project. It should also be intuitive and self-explaining. A pretty name would also be nice (and I don’t mean pretty names_like_this as opposed to ugly NamesLikeThat, I mean just in general “pretty”).

Always remember: Users can’t rename your names that easily, so choose names they’d want to type out. Type out a lot.

I find that choosing names is most difficult for exception classes. Just try to compress “I couldn’t allocate your memory because you gave me a size or alignment value that is bigger than my supported maximum. But in theory I can still allocate more memory just not that much all at once” into a single identifier. I hate it!

On of the things I need to name are the libraries themselves of course. Instead of spending hours trying to come up with nice acronyms (SFML, POCO,…) or a creative, somewhat fitting word (Boost, Catch,…) I’ll just name them after what they are for.

My library that provides string identifier classes is named string_id, my library that provides memory allocator classes is named memory and I bet you, if I ever wrote a game engine, it would be named just that - game engine.

One could argue that this is similar to the individual Boost libraries and provides direct information what the library is about, but mine are standalone and not bundled into a bigger thing. Other (dis-)advantages of this naming strategy aside I run into a very fundamental problem: The namespace name.

For example, memory is a pretty generic name - especially for a namespace. A github search yields about 15,000 code results. Using memory as top-level namespace is asking for trouble.

So instead I use my universal (and thus Github) username - foonathan - as top-level namespace and the library name is a nested namespace. So to access symbols you’d need to write foonathan::library::foo instead of library::foo.

With this I obey the following guideline.

Guideline I: Namespace names should be unique

If you are writing a library, the top-level namespace name should be the only symbol exported into the global scope.

This is reasonably enough, I hope.

The global scope is, well, global. It is shared between everything, all the libraries you use, your own code. It is already polluted by C libraries, so it can be crowded with symbols.

So it is especially important that you try to avoid name clashes; everything you put into the global scope - i.e. your top-level namespace! - should be unique.

How do you “guarantee” uniqueness? I’ve identified two strategies:

Strategy a): Use a long, expressive namespace name

The more information you put into the name, the less likely a name clash is. So just put everything into the namespace you can.

Yes, that’s ugly.

Strategy b): Use your/your organizations (Github-)name

If you are writing code that will be published on Github, there is already a unique name: your user or your organization name. Since Github is used by so many people, it is likely that the name will be globally unique as well.

So just put it into your namespace; either as top-level namespace (like I do) or as prefix.

Yes, that’s even worse.

About naming things (cont.)

I’m a library author.

I’m not narcissist, I don’t want you to type in my name each time you want to use my code.

At least my user name would be easy to type out, doesn’t contain weird number combos or stuff like that.

Thankfully, you don’t have to.

There is a tiny C++ feature regarding namespaces that is often forgotten and - judging the number of Google results - people do not talk about very often: Namespace aliases.

In case you didn’t know (which is likely): A namespace alias is just that - an alias for a namespace. Just like a typedef or template alias you can use it to introduce an alternative name for something, in this case for a certain namespace. Then you can use the new name instead (almost) everywhere you’d use the old name.

Only “almost” because you cannot use it to extend the namespace, i.e. you can’t write namespace NewName {...}. This also affects explicit template specializations.

It looks like this:

// a namespace alias
namespace NewName = OldName;

For example, in my string_id library instead of prefixing everything with foonathan::string_id::, write:

namespace sid = foonathan::string_id;
// now you can access it through sid::

And for memory such an alias is enabled by default: You can just write memory::, leaving out the top-level namespace thanks to an alias to foonathan::memory::. If you cannot use the top-level namespace name memory, there is a CMake option to disable the alias.

An automated alias will also come to string_id as soon as I start working on it again. I will soon(TM).

Update: I’ve removed the option now since it lead to complications inside the build system. Now there is a special header you have to include that provides the alias.

This leads directly to the next guideline.

Guideline II: Alias the namespaces you use

So every library has a long, ugly namespace name, since they’re all following my Guideline I.

All programmers are reading my blog, aren’t they?

What do you do? Simple: Alias the namespace to a shorter name. Your alias only need to be locally unique - in your project, that is. So you can use that fancy 3 letter abbreviation everybody seems to like.

Building on that, as a library author you can make your user’s life easier. Provide the shorter alias surrounded by e.g. #ifndef in your header file as well. As long as the user doesn’t run into a collision, it can be used without hassle. If there is a collision, the alias can simple be #define‘d out.

Macros. They’re wonderful.

This is a good compromise between a unique and pretty name without sacrificing any of those aims.

Inline namespaces

Since we’re already talking about obscure features related to namespaces, I should mention inline namespace as well. It was added in C++11 and is basically a namespace that automatically exports all symbols to the parent scope.

Well, that seems useful.

It is! I’ll write more about their use cases in the near future, for now, let’s consider only one use: version handling. Let’s say you have a fancy_allocator class.

Yes, I am still using allocators as examples for everything. At least they’re not making cat noises! (Disclaimer: I love cats, just not in C++ code)

namespace my_long_unique_lib_name // Guideline I
{
	inline namespace v1
	{
		class fancy_allocator
		{
			// fancy allocation stuff
		};
	}
}

Since v1 is an inline namespace, it is transparent to the compilers and client code can just write:

namespace lul = my_long_unique_lib_name; // Guideline II
...
lul::fancy_allocator alloc;

Time goes by and someone detects that the fancy_allocator can be made even more fancy. But this sadly removes the default constructor! So instead of removing it, the new version gets added alongside the old version:

namespace my_long_unique_lib_name // Guideline I
{
	namespace v1
	{
		class fancy_allocator
		{
			// fancy allocation stuff
		};
	}
	inline namespace v2
	{
		class fancy_allocator
		{
			// even fancier allocation stuff
		};
	}
}

Now v2 is inline, since we only want the bleeding edge stuff by default.

Yes, I am using Arch Linux as OS. How’d you guessed?

But the client code above doesn’t compile! Someone has to refactor every code using a default-constructed fancy_allocator. Luckily, thanks to namespace aliases, this is an easy fix:

namespace lul = my_long_unique_lib_name::v1; // only change!
...
lul::fancy_allocator alloc;

Since every access is done through the alias, only the alias needs to be changed to include v1 and the rest can be leaved untouched.

Now that’s an easy migration!

Refactoring the code can be done later. This technique is also recommended by Boost’s Best Practice Handbook.

Conclusion

TL;DR: namespace aliases are awesome!

Especially as a library author use a unique top-level namespace name even at the cost of making it very long and ugly. Users can alias the name to a shorter, prettier name.

A default alias - which can be disabled by macro - can also be provided by the library. This allows both: short and pretty namespace name for 99% of the users and a little bit more work for the remaining one per cent.

If every access is done through a namespace alias, the user can also easily adapt to a changing inline namespace; just change the alias.


Advertisement