Stupid C++ namespace tricks

综合编程 2018-05-16 阅读原文

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:

using wspsm = Windows::System::Profile::SystemManufacturers;
using 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:

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

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

using wsc = Windows::Security::Cryptography;
using awsc = ABI::Windows::Security::Cryptography;
using 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 bustedTo 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.

The Old New Thing

责编内容by:The Old New Thing阅读原文】。感谢您的支持!

您可能感兴趣的

Which programming language is most suitable for im... And how? I want to implement an simple enough dialog with several buttons. ...
访问windows 共享提示”找不到网络路径” 排查过程... 问题现象 windows 2008 系统搭建的文件共享服务,我们比作为A,多个windows客户端主机可以正常连接连接,但是B服务器发现断开连接后,就...
痞子衡嵌入式:PCM编码与Waveform音频文件(.wav)格式详解... 大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是 PCM编码及Waveform音频文件格式 。 嵌入式里有时候也会和音频打交道,比如最近...
VisualStudio 使用三个方法启动最新 C# 功能... 本文告诉大家如何在 VisualStudio 打开最新的 C#,现在的微软更新 C# 很快,那么如何让 VisualStudio 在项目使用最新的 本...