{"id":588,"date":"2011-02-08T20:15:26","date_gmt":"2011-02-08T20:15:26","guid":{"rendered":"http:\/\/kera.name\/articles\/?p=588"},"modified":"2011-06-22T09:26:16","modified_gmt":"2011-06-22T09:26:16","slug":"befriending-your-parser","status":"publish","type":"post","link":"https:\/\/kera.name\/articles\/2011\/02\/befriending-your-parser\/","title":{"rendered":"Tomalak&#039;s Tuesday Tip #9: Befriending Your Parser"},"content":{"rendered":"<p>In an unprecedented feat of miraculousness, Freenode&#039;s ##C++ discussion channel saw &mdash; in the space of no more than twenty minutes &mdash; the same question asked twice of one of C++&#039;s more subtle features. Just how <i>do<\/i> you declare a <code>friend<\/code> from the global namespace?<\/p>\n<p>To demonstrate the scenario, consider the following code:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">namespace N {\nstruct S {\nfriend ostream& operator<<(ostream& os, const S&);\nS() : x(0) {};\nprivate:\nint x;\n};\n}\nostream& operator<<(ostream& os, const N::S& s) {\nreturn os << s.x;\n}<\/p>\n<p>int main() {\nN::S s;\nstd::cout << s; \/\/ error: 'int N::S::x' is private\n}<\/textarea>\n<\/p>\n<p>Although the member variable <code>N::S::x<\/code> is marked private, <code>friend<\/code>ing the <code>operator&lt;&lt;<\/code> function should allow access to it; therefore, the expected output is &#034;1&#034;. But not so!<\/p>\n<p>The reason is almost disappointingly inelaborate. <code>friend<\/code> statements are, in fact, function declarations too.<\/p>\n<p>That means that when you write <code>friend ostream&amp; operator&lt;&lt;(ostream&amp; os, const S&amp;)<\/code> you&#039;re saying &#034;there&#039;s a function with this signature, and it&#039;s allowed to access stuff in me&#034;. The problem here is that the function declaration is inside the namespace <code>N<\/code>, so you&#039;ve managed to implicitly declare a function <code>ostream&amp; N::operator&lt;&lt;(ostream&amp; os, const S&amp;)<\/code>&#8230; but your actual <code>operator&lt;&lt;<\/code> is in the global namespace. You&#039;ve declared a function that you never define nor use.<\/p>\n<p>Phew!<\/p>\n<p>In itself this is harmless, but it does mean that your <code>friend<\/code> statement has nothing to do with the global <code>operator&lt;&lt;<\/code> that you actually use. Consequently, access to private or protected members from within it is still prohibited.<\/p>\n<p>The most obvious fix here is to explicitly specify that you&#039;re declaring and <code>friend<\/code>ing a function in the global namespace, using the &#034;<code>::<\/code>&#034; operator (line 6):<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">namespace N { struct S; }\nostream& operator<<(ostream& os, const N::S& s);<\/p>\n<p>namespace N {\nstruct S {\nfriend ostream& ::operator<<(ostream& os, const S&);\nS() : x(0) {};\nprivate:\nint x;\n};\n}\nostream& operator<<(ostream& os, const N::S& s) {\nreturn os << s.x;\n}<\/p>\n<p>int main() {\nN::S s;\nstd::cout << s;\n}<\/textarea>\n<\/p>\n<p>(I&#039;ve also added a couple of now-necessary forward declarations.)<\/p>\n<p><b>Going further<\/b><\/p>\n<p>This is all well and good, but let&#039;s take a look at what happens when we be<code>friend<\/code> a different function. I&#039;ve picked a simple one called <code>F<\/code> that takes a ref-to-const-<code>S<\/code> and returns an <code>int<\/code>:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">namespace N { struct S; }\nint F(const N::S& s);<\/p>\n<p>namespace N {\nstruct S {\nfriend int ::F(const S& s);\nS() : x(0) {};\nprivate:\nint x;\n};\n}\nint F(const N::S& s) {\nstd::cout << s.x;\nreturn 0;\n}<\/p>\n<p>int main() {\nN::S s;\nF(s);\n}<\/textarea>\n<\/p>\n<p>All that&#039;s really changed is that the function has a different signature.<\/p>\n<p>The key difference here is that our <code>operator&lt;&lt;<\/code> returned <code>ostream&amp;<\/code>, whereas our <code>F<\/code> returns <code>int<\/code>. One is a reference, and one is not. And the problem relates to <em>parsing<\/em>.<\/p>\n<p>Let&#039;s take a look at the two <code>friend<\/code> statements side by side:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">friend ostream& ::operator<<(ostream& os, const S&);\nfriend int ::F(const S& s);<\/textarea>\n<\/p>\n<p>In the first example, it&#039;s clear to the compiler what you are doing. <code>ostream&amp;<\/code> can only be a type (due to the placement of the <code>&amp;<\/code> symbol, and a few other things) and the rest falls into place.<\/p>\n<p>But in the second example things aren&#039;t quite so clear. The compiler doesn&#039;t care about spaces quite as much as you or I, and in fact the code would mean the same in all the following variations:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">friend int ::F(const S& s);\nfriend int :: F(const S& s);\nfriend int:: F(const S& s);\nfriend int::F(const S& s);<\/textarea>\n<\/p>\n<p>Notice how <code>int::F<\/code> could be seen as a function <code>F<\/code> inside a namespace <code>int<\/code>. However, <code>int<\/code> is a keyword and this would be quite illegal. The compiler knows this, so the example compiles successfully and means what you expect.<\/p>\n<p>But what if we didn&#039;t use <code>int<\/code>? Still returning by value, let&#039;s use a return type that isn&#039;t a keyword:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">namespace N { struct S; }\nN::S F(const N::S& s);\n\/\/ ^ note: yes, forward declaration is enough for\n\/\/    return-by-value in a function declaration!<\/p>\n<p>namespace N {\nstruct S {\nfriend S ::F(const S& s);\nS() : x(0) {};\nprivate:\nint x;\n};\n}\nN::S F(const N::S& s) {\nstd::cout << s.x;\nreturn s;\n}<\/p>\n<p>int main() {\nN::S s;\nF(s); \/\/ error: ISO C++ forbids declaration of 'F' with no type\n}<\/textarea>\n<\/p>\n<p>The compiler now sees a declaration and befriending of a function <code>S::F<\/code> that returns nothing, which is illegal. Parsing fails. And although we&#039;ve tweaked around with the code a couple of times, we&#039;ve ended up with something otherwise completely valid: this code structure is hardly unusual.<\/p>\n<p><b>The solution to rule them all<\/b><\/p>\n<p>Fortunately, we can rely on our trusty parentheses to put the topic to rest once and for all. Check out the new <code>friend<\/code> statement:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">namespace N { struct S; }\nN::S F(const N::S& s);<\/p>\n<p>namespace N {\nstruct S {\nfriend S (::F)(const S& s);\nS() : x(0) {};\nprivate:\nint x;\n};\n}\nN::S F(const N::S& s) {\nstd::cout << s.x;\nreturn s;\n}<\/p>\n<p>int main() {\nN::S s;\nF(s);\n}<\/textarea>\n<\/p>\n<p><b>Bootnote<\/b><\/p>\n<p>It may seem like I&#039;ve been describing an edge case, but this really does come up more often than one might think. Hopefully this article can serve as some kind of reference for when that day comes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In an unprecedented feat of miraculousness, Freenode&#039;s ##C++ discussion channel saw &mdash; in the space of no more than twenty minutes &mdash; the same question asked twice of one of C++&#039;s more subtle features. Just how <i>do<\/i> you declare a <code>friend<\/code> from the global namespace? I find out.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[21,20,12,33],"_links":{"self":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/588"}],"collection":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/comments?post=588"}],"version-history":[{"count":12,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/588\/revisions"}],"predecessor-version":[{"id":713,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/588\/revisions\/713"}],"wp:attachment":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/media?parent=588"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/categories?post=588"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/tags?post=588"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}