{"id":102431,"date":"2019-04-19T07:00:00","date_gmt":"2019-04-19T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=102431"},"modified":"2019-06-06T17:44:38","modified_gmt":"2019-06-07T00:44:38","slug":"20190419-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190419-00\/?p=102431","title":{"rendered":"On resolving the type vs member conflict in C++: The Color Color problem"},"content":{"rendered":"<p>In C++, there are ambiguities when a member function has the same name as a type. Consider: <\/p>\n<pre>\n\/\/ Some header file from a UI library you are using\n\nnamespace Windows::UI::Xaml\n{\n  enum class Visibility { Collapsed, Visible };\n\n  struct Style { \/* ... *\/ };\n\n  namespace Controls\n  {\n    struct UIElement\n    {\n    public:\n      \/* ... *\/\n\n      \/\/ returns current visibility\n      Windows::UI::Xaml::Visibility Visibility();\n\n      \/\/ change visibility\n      void Visibility(Windows::UI::Xaml::Visibility value);\n\n      \/\/ returns current style\n      Windows::UI::Xaml::Style Style();\n\n      \/\/ change style\n      void Style(Windows::UI::Xaml::Style value);\n    };\n  }\n}\n<\/pre>\n<p>Your project has a custom element, say like this: <\/p>\n<pre>\nnamespace MyProject\n{\n  class CustomElement : public Windows::UI::Xaml::Controls::UIElement\n  {\n    void OnThemeChanged();\n  };\n}\n<\/pre>\n<p>And now you are implementing the <code>On&shy;Theme&shy;Changed<\/code> method. <\/p>\n<pre>\nusing namespace Windows::UI::Xaml;\n\nvoid MyProject::CustomElement::OnThemeChanged()\n{\n  \/\/ Find out what style to use.\n  Style style = GetStyleFromCurrentTheme();\n\n  \/\/ Set it as our style.\n  Style(style);\n}\n<\/pre>\n<p>This code doesn&#8217;t compile. The word <code>Style<\/code> can mean multiple things: <\/p>\n<ul>\n<li>It could refer to the class <code>Windows::<\/code><code>UI::<\/code><code>Xaml::<\/code><code>Style<\/code>. <\/li>\n<li>It could refer to the method <code>MyProject::<\/code><code>Custom&shy;Element::<\/code><code>Style()<\/code>. <\/li>\n<\/ul>\n<p>C++ <a HREF=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/unqualified_lookup#Member_function_definition\">unqualified name lookup in member functions<\/a> searches the class before searching in namespaces, so it finds the method <code>Custom&shy;Element::<\/code><code>Style()<\/code>. <a HREF=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/sfinae\">SFINAE<\/a> does not apply, so if the name inside the class doesn&#8217;t make sense, the compiler doesn&#8217;t keep looking for a better match; it simply reports an error.  Depending on how you used the name <code>Style<\/code>, the error message will vary, but whatever it is, it is usually incomprehensible. <\/p>\n<p><pre>\nerror: expected ';' before 'style'\nerror: statement cannot resolve address of overloaded function\n\nerror: cannot determine which instance of overloaded function\n'MyProject::CustomElement::Style' is intended\nerror: expected a \";\"\n\nerror: syntax error: missing ';' before identifier 'style'\nerror: non-standard syntax; use '&amp;' to create a pointer to member\n<\/pre>\n<p>These error messages make sense once you realize that the compiler resolved <code>Style<\/code> to the member function. It&#8217;s a case of an error message written with compiler-colored glasses. To be fair, the compiler doesn&#8217;t realize that it&#8217;s wearing glasses. It&#8217;s simply following the rules for unqualified name resolution and reporting the problems with the name you chose by mistake. <\/p>\n<p>The only compiler I found that generates a helpful error is clang, which goes the extra mile and realizes that the name the language rules require it to choose may not have been the name you intended. <\/p>\n<pre>\nerror: must use 'struct' tag to refer to type 'Style' in this scope\nnote: struct 'Style' is hidden by a non-type declaration of 'Style' here\n      Windows::UI::Xaml::Style Style();\n<\/pre>\n<p>The clang compiler even provides a suggestion as to how you can force the name to be resolved the way you intended. <\/p>\n<pre>\nvoid MyProject::CustomElement::OnThemeChanged()\n{\n  \/\/ Find out what style to use.\n  <font COLOR=\"blue\">struct<\/font> Style style = GetStyleFromCurrentTheme();\n\n  \/\/ Set it as our style.\n  Style(style);\n}\n<\/pre>\n<p>Alternatively, you can use the scope resolution operator to force the name to be looked up in the global scope: <\/p>\n<pre>\nvoid MyProject::CustomElement::OnThemeChanged()\n{\n  \/\/ Find out what style to use.\n  <font COLOR=\"blue\">::<\/font>Style style = GetStyleFromCurrentTheme();\n\n  \/\/ Set it as our style.\n  Style(style);\n}\n<\/pre>\n<p>The global lookup will work because you did a <code>using namespace Windows:<\/code><code>:UI::<\/code><code>Xaml;<\/code> to import the names from that namespace into the global namespace. After all, that&#8217;s what led you to believe that writing simply <code>Style<\/code> was good enough in the first place. <\/p>\n<p>This problem also exists with the <code>Visibility<\/code> enumeration: <\/p>\n<pre>\nvoid MyProject::CustomElement::OnThemeChanged()\n{\n  \/\/ See if we should be visible in the current theme.\n  Visibility visibility = IsVisibleInCurrentTheme();\n  \/\/^^^^^^^^ compiler error here\n\n  \/\/ Set it as our new visibility.\n  Visibility(visibility);\n}\n<\/pre>\n<p>The solution is the same. You need to quailfy the name in a way that prevents the compiler from considering the member function. You could say <code>enum Visibility<\/code>, or you could say <code>::Visibility<\/code>. <\/p>\n<p>Note, however, that there is no problem here: <\/p>\n<pre>\nvoid MyProject::CustomElement::OnThemeChanged()\n{\n  \/\/ Always hide on theme change.\n  Visibility(Visibility::Collapsed);\n  \/\/         ^^^^^^^^^^ no ambiguity here\n}\n<\/pre>\n<p>There is no ambiguity in this case because of a special rule for unqualified name lookup that <a HREF=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/unqualified_lookup\">excludes functions, variables, and enumeration fields if the name is followed by a <code>::<\/code><\/a>. <\/p>\n<p>The case of a member with the same name as a type is called the <a HREF=\"http:\/\/web.archive.org\/web\/20190119001817\/https:\/\/blogs.msdn.microsoft.com\/ericlippert\/2009\/07\/06\/color-color\/\">Color Color problem<\/a>, and the C# language &#8220;<a HREF=\"https:\/\/softwareengineering.stackexchange.com\/a\/212772\">was specifically designed to permit&#8221; it<\/a>. Unfortunately, the C++ language struggles with it. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>You have to nudge the compiler in the right direction.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-102431","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You have to nudge the compiler in the right direction.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102431","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=102431"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102431\/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=102431"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=102431"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=102431"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}