Stupid C++ namespace tricks


These tricks may be obvious, but at least I'm going to write them down.

It is common to import an entire namespace into the global namespace. I'm not saying it's a good idea, but it is common. The most notorious example is to put

using namespace std;

to import the std namespace into the global namespace.

When working with the Windows Runtime, you often have rather deep namespaces. For example, we saw some time ago that we were operating in the Windows::System::Profile::System­Manufacturers namespace. This is quite a mouthful, and it is common to put a

using namespace Windows::System::Profile::SystemManufacturers;

in your program just to save yourself the hassle of typing it all out.

However, things get complicated if you create name collisions.

For example, if you are using WRL, you will be working with the ABI::Windows::System::Profile::System­Manufacturers namespace, but if you do a

using namespace ABI::Windows::System::Profile::SystemManufacturers;

you now have a problem because you have imported the name Smbios­Information twice:

using namespace Windows::System::Profile::SystemManufacturers;
using namespace ABI::Windows::System::Profile::SystemManufacturers;

After these two declarations, the name System­Information is now ambiguous. It could refer to Windows::System::Profile::System­Manufacturers::System­Information, via the first using declaration, or it oculd refer to ABI::Windows::System::Profile::System­Manufacturers::System­Information, via the second using declaration.

I've worked around this by using namespace aliases:

namespace wspsm = Windows::System::Profile::SystemManufacturers;
namespace awspsm = ABI::Windows::System::Profile::SystemManufacturers;

This lets me use wspsm::Smbios­Information and awspsm::Smbios­Information to refer to the C++/CX or ABI versions, respectively.

However, this gets clunky once you have multiple namespaces you want to access:

namespace wspsm = Windows::System::Profile::SystemManufacturers;
namespace awspsm = ABI::Windows::System::Profile::SystemManufacturers;
namespace wwspsm = winrt::Windows::System::Profile::SystemManufacturers;

namespace wuvm = Windows::UI::ViewManagement;
namespace awuvm = ABI::Windows::UI::ViewManagement;
namespace wwuvm = winrt::Windows::UI::ViewManagement;

namespace wsc = Windows::Security::Cryptography;
namespace awsc = ABI::Windows::Security::Cryptography;
namespace wwsc = winrt::Windows::Security::Cryptography;

because you have to juggle all these aliases.

But there's a more attractive solution: Move names around by importing them into another namespace. (The name for this technique is "namespace composition", covered in sections 14.4.3 and 14.4.4 of The C++ Programming Language.)

namespace ABI
{
  using Windows::System::Profile::SystemManufacturers;
  using Windows::UI::ViewManagement;
  using Windows::Security::Cryptography;
}

namespace cx
{
  using Windows::System::Profile::SystemManufacturers;
  using Windows::UI::ViewManagement;
  using Windows::Security::Cryptography;
}

namespace winrt
{
  using Windows::System::Profile::SystemManufacturers;
  using Windows::UI::ViewManagement;
  using Windows::Security::Cryptography;
}

The first block of using declarations imports the contents of the ABI::Windows::System::Profile::System­Manufacturers, ABI::Windows::UI::View­Management, and ABI::Windows::Security::Cryptography namespaces into the ABI namespace.

Similarly for the other two blocks.

The upshot of this is that you can now do this

Old and busted To get
New hotness
awspsm::Smbios­Information    ABI::Windows::System::Profile::System­Manufacturers::SmbiosInformation
   ABI::Smbios­Information
 wspsm::Smbios­Information         Windows::System::Profile::System­Manufacturers::SmbiosInformation
    cx::Smbios­Information
wwspsm::Smbios­Information  winrt::Windows::System::Profile::System­Manufacturers::SmbiosInformation
 winrt::Smbios­Information
 awuvm::Application­View    ABI::Windows::UI::View­Management::Application­View
   ABI::Application­View
  wuvm::Application­View         Windows::UI::View­Management::Application­View
    cx::Application­View
 wwuvm::Application­View  winrt::Windows::UI::View­Management::Application­View
 winrt::Application­View
  awsc::Cryptographic­Buffer    ABI::Windows::Security::Cryptography::Cryptographic­Buffer
   ABI::Cryptographic­Buffer
   wsc::Cryptographic­Buffer         Windows::Security::Cryptography::Cryptographic­Buffer
    cx::Cryptographic­Buffer
  wwsc::Cryptographic­Buffer  winrt::Windows::Security::Cryptography::Cryptographic­Buffer
winrt::Cryptographic­Buffer

In particular, this trick works with Windows Runtime classes because as a general rule, Windows Runtime type names are unique across all Windows Runtime namespaces, so you won't inadvertently introduce a name collision by using a bunch of Windows Runtime namespaces together.

The general rule makes Windows Runtime types easier to search for (both on the Web and in your code) because you will have fewer false positives.

Bonus chatter: The exception to the general rule is DirectX. Windows Runtime naming conventions permit the same name to be used in different versions of DirectX. This isn't a problem because in practice, each application picks one version of DirectX and sticks with it; applications don't try to mix-and-match different versions of DirectX.

Bonus bonus chatter: The above rule is on the books, but has yet to be exercised. As of this writing, the only version of DirectX in the Windows Runtime is DirectX11.

Comments (14)

  1. Ray Koopa says:

    And of course you do all the using namespace statements in your header files. So your colleagues don’t miss out on your awesome ideas when including then.

  2. Rich says:

    *Applause* !!!

  3. When reading/using such deep namespace I’m always reminded of one of Butterworth’s ironic posts, namely https://punchlet.wordpress.com/2011/06/18/letter-the-sixth-belatedly/

    And then I (yes, modesty allows me to admit) had a wonderful idea. Why can we not take advantage of our patient’s mania for hierarchy? Can we not encourage them to write code like this:

    namespace MyLibrary {
    namespace Useful {
    namespace Utility {
    int f();
    }
    namespace Business {
    int f();
    namespace Utility {
    int f();
    }
    }
    }
    }

    It turns out that almost no encouragement is needed. Humans apparently actually like writing stuff like this:

    MyLibrary::Useful::Business::Utility::f();

    and when they have done so seem to think they have done something profound. The thought of naming the functions so that their own names are distinct seems repellent to them. And even when the names are distinct, and there is absolutely no reason to use these ludicrous constructs, they will still embrace them as they would long-lost lovers.

    1. pc says:

      Thank you so much for sharing this site. I now want all content about programming to be in Screwtape Letters format.

  4. Peter Doubleday says:

    This is rather wonderful. I wouldn’t call it a “stupid trick,” per se, because after all a namespace is just an aliasing mechanism. Rather, it’s a composite alias mechanism for aliases.

    If you have a sufficiently large .NET code-base, it might even be worth thinking about there. Isn’t using a wonderful keyword?

  5. Jason Knight says:

    Isn’t there a mistake on this? Shouldn’t the “inner namespaces” be different from each other? All three are importing the same Windows::* namespaces! Shouldn’t it be:

    namespace ABI {
    using ABI::Windows::System::Profile::SystemManufacturers;
    ……
    }

    ???

  6. Jan says:

    Maybe I read it wrong, but I would expect that ABI:: and winrt:: are missing in the examples of the namespaces (all 3 are identical at the moment).

    1. Ben Voigt says:

      The code’s already *in* that namespace, so it will automatically lookup names qualified relative to it.

  7. Aged .Net Guy says:

    Looks like cut-n-paste coding strikes again. Happens to the very best of us apparently.

    One of the nice things about being retired from active devving is that it’s now been _months_ since I last made that mistake myself. :)

    1. Ben Voigt says:

      Nope, just context-dependent meaning, so someone who blindly copy+pastes this code to a function living in a different namespace will have the meaning mysteriously and completely change.

  8. Marvy says:

    re: Windows Runtime type names are unique across all Windows Runtime namespaces

    So why not just use one namespace and let the compiler enforce that rule?

    1. I can’t tell if you’re being serious or silly.

      1. Mark Yagnatinsky says:

        Almost serious

  9. Mike says:

    Perhaps it’s me, but when C++ first emerged, it’s great attraction was the ability to encapsulate code and hide implementation within the objects you were building. As the years went by, ever more complex mechanisms were introduced to allow the real-world access needed to object data and methods. Ever more complex aliasing and namespace usages were born to avoid the use of global variables whilst simultaneously creating ever more esoteric ways of actually having them in all but name but hiding that fact!

    After many years, I finally gave up using C++ because it was harder to understand and use the language than it was to solve the problems I was coding for. The above article illustrates why – for me anyway – very well.

    8)

Skip to main content