{"id":98765,"date":"2018-05-16T07:00:00","date_gmt":"2018-05-16T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=98765"},"modified":"2022-11-15T17:08:17","modified_gmt":"2022-11-16T01:08:17","slug":"20180516-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20180516-00\/?p=98765","title":{"rendered":"C++ namespace parlor tricks"},"content":{"rendered":"<p>These tricks may be obvious, but at least I&#8217;m going to write them down.<\/p>\n<p>It is common to import an entire namespace into the global namespace. <a href=\"https:\/\/stackoverflow.com\/questions\/1452721\/why-is-using-namespace-std-considered-bad-practice\"> I&#8217;m not saying it&#8217;s a good idea<\/a>, but it is common. The most notorious example is to put<\/p>\n<pre>using namespace std;\r\n<\/pre>\n<p>to import the <code>std<\/code> namespace into the global namespace.<\/p>\n<p>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 <code>Windows::<wbr \/>System::<wbr \/>Profile::<wbr \/>System\u00adManufacturers<\/code> namespace. This is quite a mouthful, and it is common to put a<\/p>\n<pre>using namespace Windows::System::Profile::SystemManufacturers;\r\n<\/pre>\n<p>in your program just to save yourself the hassle of typing it all out.<\/p>\n<p>However, things get complicated if you create name collisions.<\/p>\n<p>For example, if you are using WRL, you will be working with the <code>ABI::<wbr \/>Windows::<wbr \/>System::<wbr \/>Profile::<wbr \/>System\u00adManufacturers<\/code> namespace, but if you do a<\/p>\n<pre>using namespace ABI::Windows::System::Profile::SystemManufacturers;\r\n<\/pre>\n<p>you now have a problem because you have imported the name <code>Smbios\u00adInformation<\/code> twice:<\/p>\n<pre>using namespace Windows::System::Profile::SystemManufacturers;\r\nusing namespace ABI::Windows::System::Profile::SystemManufacturers;\r\n<\/pre>\n<p>After these two declarations, the name <code>System\u00adInformation<\/code> is now ambiguous. It could refer to <code>Windows::<wbr \/>System::<wbr \/>Profile::<wbr \/>System\u00adManufacturers::<wbr \/>System\u00adInformation<\/code>, via the first <code>using<\/code> declaration, or it oculd refer to <code>ABI::<wbr \/>Windows::<wbr \/>System::<wbr \/>Profile::<wbr \/>System\u00adManufacturers::<wbr \/><code>System\u00adInformation<\/code>, via the second <code>using<\/code> declaration. <\/code><\/p>\n<p>I&#8217;ve worked around this by using namespace aliases:<\/p>\n<pre>namespace wspsm = Windows::System::Profile::SystemManufacturers;\r\nnamespace awspsm = ABI::Windows::System::Profile::SystemManufacturers;\r\n<\/pre>\n<p>This lets me use <code>wspsm::Smbios\u00adInformation<\/code> and <code>awspsm::Smbios\u00adInformation<\/code> to refer to the C++\/CX or ABI versions, respectively.<\/p>\n<p>However, this gets clunky once you have multiple namespaces you want to access:<\/p>\n<pre>namespace wspsm = Windows::System::Profile::SystemManufacturers;\r\nnamespace awspsm = ABI::Windows::System::Profile::SystemManufacturers;\r\nnamespace wwspsm = winrt::Windows::System::Profile::SystemManufacturers;\r\n\r\nnamespace wuvm = Windows::UI::ViewManagement;\r\nnamespace awuvm = ABI::Windows::UI::ViewManagement;\r\nnamespace wwuvm = winrt::Windows::UI::ViewManagement;\r\n\r\nnamespace wsc = Windows::Security::Cryptography;\r\nnamespace awsc = ABI::Windows::Security::Cryptography;\r\nnamespace wwsc = winrt::Windows::Security::Cryptography;\r\n<\/pre>\n<p>because you have to juggle all these aliases. &lt;\/`P&gt;<\/p>\n<p>But there&#8217;s a more attractive solution: Move names around by importing them into another namespace. (The name for this technique is &#8220;namespace composition&#8221;, covered in <a href=\"https:\/\/www.safaribooksonline.com\/library\/view\/the-c-programming\/9780133522884\/#toc\"> sections 14.4.3 and 14.4.4<\/a> of <a href=\"https:\/\/www.amazon.com\/gp\/product\/0321563840\/?ie=UTF8&amp;tag=tholneth-20\"> <i>The C++ Programming Language<\/i><\/a>.)<\/p>\n<pre>namespace ABI\r\n{\r\n  using Windows::System::Profile::SystemManufacturers;\r\n  using Windows::UI::ViewManagement;\r\n  using Windows::Security::Cryptography;\r\n}\r\n\r\nnamespace cx\r\n{\r\n  using Windows::System::Profile::SystemManufacturers;\r\n  using Windows::UI::ViewManagement;\r\n  using Windows::Security::Cryptography;\r\n}\r\n\r\nnamespace winrt\r\n{\r\n  using Windows::System::Profile::SystemManufacturers;\r\n  using Windows::UI::ViewManagement;\r\n  using Windows::Security::Cryptography;\r\n}\r\n<\/pre>\n<p>The first block of <code>using<\/code> declarations imports the contents of the <code>ABI::<wbr \/>Windows::<wbr \/>System::<wbr \/>Profile::<wbr \/>System\u00adManufacturers<\/code>, <code>ABI::<wbr \/>Windows::<wbr \/>UI::<wbr \/>View\u00adManagement<\/code>, and <code>ABI::<wbr \/>Windows::<wbr \/>Security::<wbr \/>Cryptography<\/code> namespaces into the <code>ABI<\/code> namespace.<\/p>\n<p>Similarly for the other two blocks.<\/p>\n<p>The upshot of this is that you can now do this<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Old and busted<\/th>\n<th rowspan=\"2\">To get<\/th>\n<\/tr>\n<tr>\n<th>New hotness<\/th>\n<\/tr>\n<tr>\n<td><code>awspsm::<wbr \/>Smbios\u00adInformation<\/code><\/td>\n<td rowspan=\"2\">\n<div style=\"text-align: right;\"><code>ABI::<wbr \/>Windows::<wbr \/>System::<wbr \/>Profile::<\/code><\/div>\n<div style=\"text-align: right;\"><code>System\u00adManufacturers::SmbiosInformation<\/code><\/div>\n<\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0\u00a0\u00a0ABI::<wbr \/>Smbios\u00adInformation<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0wspsm::<wbr \/>Smbios\u00adInformation<\/code><\/td>\n<td rowspan=\"2\">\n<div style=\"text-align: right;\"><code>Windows::<wbr \/>System::<wbr \/>Profile::<\/code><\/div>\n<div style=\"text-align: right;\"><code>System\u00adManufacturers::SmbiosInformation<\/code><\/div>\n<\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0\u00a0\u00a0\u00a0cx::<wbr \/>Smbios\u00adInformation<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>wwspsm::<wbr \/>Smbios\u00adInformation<\/code><\/td>\n<td rowspan=\"2\">\n<div style=\"text-align: right;\"><code>winrt::<wbr \/>Windows::<wbr \/>System::<wbr \/>Profile::<\/code><\/div>\n<div style=\"text-align: right;\"><code>System\u00adManufacturers::SmbiosInformation<\/code><\/div>\n<\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0winrt::<wbr \/>Smbios\u00adInformation<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0awuvm::<wbr \/>Application\u00adView<\/code><\/td>\n<td rowspan=\"2\">\n<div style=\"text-align: right;\"><code>ABI::<wbr \/>Windows::<wbr \/>UI::<wbr \/>View\u00adManagement::<\/code><\/div>\n<div style=\"text-align: right;\"><code>Application\u00adView<\/code><\/div>\n<\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0\u00a0\u00a0ABI::<wbr \/>Application\u00adView<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0\u00a0wuvm::<wbr \/>Application\u00adView<\/code><\/td>\n<td rowspan=\"2\">\n<div style=\"text-align: right;\"><code>Windows::<wbr \/>UI::<wbr \/>View\u00adManagement::<\/code><\/div>\n<div style=\"text-align: right;\"><code>Application\u00adView<\/code><\/div>\n<\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0\u00a0\u00a0\u00a0cx::<wbr \/>Application\u00adView<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0wwuvm::<wbr \/>Application\u00adView<\/code><\/td>\n<td rowspan=\"2\">\n<div style=\"text-align: right;\"><code>winrt::<wbr \/>Windows::<wbr \/>UI::<wbr \/>View\u00adManagement::<\/code><\/div>\n<div style=\"text-align: right;\"><code>Application\u00adView<\/code><\/div>\n<\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0winrt::<wbr \/>Application\u00adView<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0\u00a0awsc::<wbr \/>Cryptographic\u00adBuffer<\/code><\/td>\n<td rowspan=\"2\">\n<div style=\"text-align: right;\"><code>ABI::<wbr \/>Windows::<wbr \/>Security::<wbr \/>Cryptography::<\/code><\/div>\n<div style=\"text-align: right;\"><code>Cryptographic\u00adBuffer<\/code><\/div>\n<\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0\u00a0\u00a0ABI::<wbr \/>Cryptographic\u00adBuffer<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0\u00a0\u00a0wsc::<wbr \/>Cryptographic\u00adBuffer<\/code><\/td>\n<td rowspan=\"2\">\n<div style=\"text-align: right;\"><code>Windows::<wbr \/>Security::<wbr \/>Cryptography::<\/code><\/div>\n<div style=\"text-align: right;\"><code>Cryptographic\u00adBuffer<\/code><\/div>\n<\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0\u00a0\u00a0\u00a0cx::<wbr \/>Cryptographic\u00adBuffer<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0\u00a0wwsc::<wbr \/>Cryptographic\u00adBuffer<\/code><\/td>\n<td rowspan=\"2\">\n<div style=\"text-align: right;\"><code>winrt::<wbr \/>Windows::<wbr \/>Security::<wbr \/>Cryptography::<\/code><\/div>\n<div style=\"text-align: right;\"><code>Cryptographic\u00adBuffer<\/code><\/div>\n<\/td>\n<\/tr>\n<tr>\n<td><code>\u00a0winrt::<wbr \/>Cryptographic\u00adBuffer<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>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&#8217;t inadvertently introduce a name collision by <code>using<\/code> a bunch of Windows Runtime namespaces together.<\/p>\n<p>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.<\/p>\n<p><b>Bonus chatter<\/b>: 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&#8217;t a problem because in practice, each application picks one version of DirectX and sticks with it; applications don&#8217;t try to mix-and-match different versions of DirectX.<\/p>\n<p><b>Bonus bonus chatter<\/b>: 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.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Shuffling names around.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-98765","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Shuffling names around.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/98765","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=98765"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/98765\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=98765"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=98765"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=98765"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}