Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>With respect to the other answers: We're dealing explicitly with <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3638.html">n3638</a> here, and how it's incorporated in the recent drafts of C++1y.</p> <p>I'm using 9514cc28 from the <a href="https://github.com/cplusplus/draft">commitee's github repository</a>, which incorporates some (minor) fixes/changes to n3638 already.</p> <p>n3638 allows explicitly:</p> <pre><code>struct A { auto f(); // forward declaration }; auto A::f() { return 42; } </code></pre> <p>And, as we can infer from [dcl.spec.auto], where this feature is specified, even the following will be legal:</p> <pre><code>struct A { auto f(); // forward declaration }; A x; auto A::f() { return 42; } int main() { x.f(); } </code></pre> <p>(but more on this later)</p> <p>This is fundamentally different from any <em>trailing-return-type</em> or dependent name lookup, as <code>auto f();</code> is a preliminary declaration, similar to <code>struct A;</code>. It needs to be completed later on, before it is used (before the return type is required).</p> <p>Additionally, the problems in the OP are related to internal compiler errors. The recent clang++3.4 trunk 192325 Debug+Asserts build fails to compile as an assertion fails while parsing the line <code>return L.b_ == R.b_;</code>. I have not checked with a recent version of g++ as of now.</p> <hr> <p>Is the OP's example legal wrt to a n3638?</p> <p>This is a bit tricky IMO. (I'm always referring to 9514cc28 in this section.)</p> <h3>1. Where is it allowed to use `auto`?</h3> <p>[dcl.spec.auto]</p> <blockquote> <p>6 &nbsp;&nbsp; A program that uses <code>auto</code> or <code>decltype(auto)</code> in a context not explicitly allowed in this section is ill-formed.</p> <p>2 &nbsp;&nbsp; The placeholder type can appear with a function declarator in the <em>decl-specifier-seq</em>, <em>type-specifier-seq</em>, <em>conversion-function-id</em>, or <em>trailing-return-type</em>, in any context where such a declarator is valid.</p> </blockquote> <p>/5 also defines some contexts, but they're irrelevant here.</p> <p>Therefore, <code>auto func()</code> and <code>auto operator@(..)</code> are generally allowed (this follows from the composition of a function declaration as <code>T D</code>, where <code>T</code> is of the form <em>decl-specifier-seq</em>, and <code>auto</code> is a <em>type-specifier</em>).</p> <hr> <h3>2. Is it allowed to write `auto func();`, i.e. a declaration that is not a definition?</h3> <p>[dcl.spec.auto]/1 says</p> <blockquote> <p>The <code>auto</code> and <code>decltype(auto)</code> <em>type-specifiers</em> designate a placeholder type that will be replaced later, either by deduction from an initializer or by explicit specification with a <em>trailing-return-type</em>.</p> </blockquote> <p>and /2</p> <blockquote> <p>If the declared return type of the function contains a placeholder type, the return type of the function is deduced from <code>return</code> statements in the body of the function, if any.</p> </blockquote> <p>Although it doesn't <em>explicitly</em> allow a declaration like <code>auto f();</code> for a function (that is, a declaration without definition), it is clear from n3638 and [dcl.spec.auto]/11 that it is intended to be allowed, and not explicitly forbidden.</p> <hr> <h3>3. What about friend functions?</h3> <p>So far, the example</p> <pre><code>struct A { int a_; friend auto operator==(A const&amp; L, A const&amp; R); } auto operator==(A const&amp; L, A const&amp; R) { return L.a_ == R.a_; } </code></pre> <p>should be well-formed. The interesting part now is the definition of the friend function inside the definition of <code>A</code>, that is</p> <pre><code>struct A { int a_; friend auto operator==(A const&amp; L, A const&amp; R) { return L.a_ == R.a_; } // allowed? } </code></pre> <p>In my opinion, it is allowed. To support this, I'll cite name lookup. The name lookup inside the definition of functions defined in a friend function declaration follows the name lookup of member functions as per [basic.lookup.unqual]/9. /8 of the same section specifies unqualified lookup for names used inside member function bodies. One of the ways a name can be declared to be used is that it "shall be a member of class <code>X</code> or be a member of a base class of <code>X</code> (10.2)". This allows the widely known</p> <pre><code>struct X { void foo() { m = 42; } int m; }; </code></pre> <p>Note how <code>m</code> isn't declared before its use in <code>foo</code>, but it's a member of <code>X</code>.</p> <p>From this, I conclude that even</p> <pre><code>struct X { auto foo() { return m; } int m; } </code></pre> <p>is allowed. This is supported by clang++3.4 trunk 192325. Name lookup requires to interpret this function only after the <code>struct</code> has been completed, also consider:</p> <pre><code>struct X { auto foo() { return X(); } X() = delete; }; </code></pre> <p>Similarly, the body of friend functions defined inside a class can only be interpreted once the class is complete.</p> <hr> <h3>4. What about templates?</h3> <p>Specifically, what about <code>friend auto some_function(B const&amp; L) { return L.b_; }</code>?</p> <p>First, the <em>injected-class-name</em> <code>B</code> is equivalent to <code>B&lt;T&gt;</code>, see [temp.local]/1. It refers to the <em>current instantiation</em> ([temp.dep.type]/1).</p> <p>The <em>id-expression</em> <code>L.b_</code> refers to a <em>member of the current instantiation</em> (/4). It is also a <em>dependent member of the current instantiation</em> -- this is an addition made after C++11, see <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1471">DR1471</a>, and I don't know what to think about it: [temp.dep.expr]/5 states this <em>id-expression</em> is <em>not</em> type-dependent, and as far as I see [temp.dep.constexpr] doesn't say it's value-dependent.</p> <p>If the name in <code>L.b_</code> was not dependent, name lookup would follow the "usual name lookup" rules per [temp.nondep]. Else, this'll be fun (dependent name lookup is not very well specified), but considering that</p> <pre><code>template&lt;class T&gt; struct A { int foo() { return m; } int m; }; </code></pre> <p>is accepted by most compilers as well, I think the version with <code>auto</code> should be valid, too.</p> <p>There's also a section about friends of templates in [temp.friend], but IMO it doesn't shed light on the name lookup here.</p> <hr> <p>Also see <a href="https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/jahm7_tIN1Q/discussion">this highly relevant discussion in the isocpp-forum</a>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload