summaryrefslogtreecommitdiff
path: root/devdocs/gcc~13/name-lookup.html
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2024-04-07 13:41:34 -0500
committerCraig Jennings <c@cjennings.net>2024-04-07 13:41:34 -0500
commit754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch)
treef1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/gcc~13/name-lookup.html
new repository
Diffstat (limited to 'devdocs/gcc~13/name-lookup.html')
-rw-r--r--devdocs/gcc~13/name-lookup.html39
1 files changed, 39 insertions, 0 deletions
diff --git a/devdocs/gcc~13/name-lookup.html b/devdocs/gcc~13/name-lookup.html
new file mode 100644
index 00000000..ab74435c
--- /dev/null
+++ b/devdocs/gcc~13/name-lookup.html
@@ -0,0 +1,39 @@
+<div class="subsection-level-extent" id="Name-lookup"> <div class="nav-panel"> <p> Next: <a href="temporaries" accesskey="n" rel="next">Temporaries May Vanish Before You Expect</a>, Previous: <a href="static-definitions" accesskey="p" rel="prev">Declare <em class="emph">and</em> Define Static Members</a>, Up: <a href="c_002b_002b-misunderstandings" accesskey="u" rel="up">Common Misunderstandings with GNU C++</a> [<a href="index#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="indices" title="Index" rel="index">Index</a>]</p> </div> <h1 class="subsection" id="Name-Lookup_002c-Templates_002c-and-Accessing-Members-of-Base-Classes"><span>14.7.2 Name Lookup, Templates, and Accessing Members of Base Classes<a class="copiable-link" href="#Name-Lookup_002c-Templates_002c-and-Accessing-Members-of-Base-Classes"> ¶</a></span></h1> <p>The C++ standard prescribes that all names that are not dependent on template parameters are bound to their present definitions when parsing a template function or class.<a class="footnote" id="DOCF9" href="#FOOT9"><sup>9</sup></a> Only names that are dependent are looked up at the point of instantiation. For example, consider </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">void foo(double);
+
+struct A {
+ template &lt;typename T&gt;
+ void f () {
+ foo (1); // <span class="r">1</span>
+ int i = N; // <span class="r">2</span>
+ T t;
+ t.bar(); // <span class="r">3</span>
+ foo (t); // <span class="r">4</span>
+ }
+
+ static const int N;
+};</pre>
+</div> <p>Here, the names <code class="code">foo</code> and <code class="code">N</code> appear in a context that does not depend on the type of <code class="code">T</code>. The compiler will thus require that they are defined in the context of use in the template, not only before the point of instantiation, and will here use <code class="code">::foo(double)</code> and <code class="code">A::N</code>, respectively. In particular, it will convert the integer value to a <code class="code">double</code> when passing it to <code class="code">::foo(double)</code>. </p> <p>Conversely, <code class="code">bar</code> and the call to <code class="code">foo</code> in the fourth marked line are used in contexts that do depend on the type of <code class="code">T</code>, so they are only looked up at the point of instantiation, and you can provide declarations for them after declaring the template, but before instantiating it. In particular, if you instantiate <code class="code">A::f&lt;int&gt;</code>, the last line will call an overloaded <code class="code">::foo(int)</code> if one was provided, even if after the declaration of <code class="code">struct A</code>. </p> <p>This distinction between lookup of dependent and non-dependent names is called two-stage (or dependent) name lookup. G++ implements it since version 3.4. </p> <p>Two-stage name lookup sometimes leads to situations with behavior different from non-template codes. The most common is probably this: </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">template &lt;typename T&gt; struct Base {
+ int i;
+};
+
+template &lt;typename T&gt; struct Derived : public Base&lt;T&gt; {
+ int get_i() { return i; }
+};</pre>
+</div> <p>In <code class="code">get_i()</code>, <code class="code">i</code> is not used in a dependent context, so the compiler will look for a name declared at the enclosing namespace scope (which is the global scope here). It will not look into the base class, since that is dependent and you may declare specializations of <code class="code">Base</code> even after declaring <code class="code">Derived</code>, so the compiler cannot really know what <code class="code">i</code> would refer to. If there is no global variable <code class="code">i</code>, then you will get an error message. </p> <p>In order to make it clear that you want the member of the base class, you need to defer lookup until instantiation time, at which the base class is known. For this, you need to access <code class="code">i</code> in a dependent context, by either using <code class="code">this-&gt;i</code> (remember that <code class="code">this</code> is of type <code class="code">Derived&lt;T&gt;*</code>, so is obviously dependent), or using <code class="code">Base&lt;T&gt;::i</code>. Alternatively, <code class="code">Base&lt;T&gt;::i</code> might be brought into scope by a <code class="code">using</code>-declaration. </p> <p>Another, similar example involves calling member functions of a base class: </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">template &lt;typename T&gt; struct Base {
+ int f();
+};
+
+template &lt;typename T&gt; struct Derived : Base&lt;T&gt; {
+ int g() { return f(); };
+};</pre>
+</div> <p>Again, the call to <code class="code">f()</code> is not dependent on template arguments (there are no arguments that depend on the type <code class="code">T</code>, and it is also not otherwise specified that the call should be in a dependent context). Thus a global declaration of such a function must be available, since the one in the base class is not visible until instantiation time. The compiler will consequently produce the following error message: </p> <div class="example smallexample"> <pre class="example-preformatted" data-language="cpp">x.cc: In member function `int Derived&lt;T&gt;::g()':
+x.cc:6: error: there are no arguments to `f' that depend on a template
+ parameter, so a declaration of `f' must be available
+x.cc:6: error: (if you use `-fpermissive', G++ will accept your code, but
+ allowing the use of an undeclared name is deprecated)</pre>
+</div> <p>To make the code valid either use <code class="code">this-&gt;f()</code>, or <code class="code">Base&lt;T&gt;::f()</code>. Using the <samp class="option">-fpermissive</samp> flag will also let the compiler accept the code, by marking all function calls for which no declaration is visible at the time of definition of the template for later lookup at instantiation time, as if it were a dependent call. We do not recommend using <samp class="option">-fpermissive</samp> to work around invalid code, and it will also only catch cases where functions in base classes are called, not where variables in base classes are used (as in the example above). </p> <p>Note that some compilers (including G++ versions prior to 3.4) get these examples wrong and accept above code without an error. Those compilers do not implement two-stage name lookup correctly. </p> </div> <div class="footnotes-segment"> <h1 class="footnotes-heading">Footnotes</h1> <h2 class="footnote-body-heading"><a id="FOOT9" href="#DOCF9">(9)</a></h2> <p>The C++ standard just uses the term “dependent” for names that depend on the type or value of template parameters. This shorter term will also be used in the rest of this section.</p> </div> <div class="nav-panel"> <p> Next: <a href="temporaries">Temporaries May Vanish Before You Expect</a>, Previous: <a href="static-definitions">Declare <em class="emph">and</em> Define Static Members</a>, Up: <a href="c_002b_002b-misunderstandings">Common Misunderstandings with GNU C++</a> [<a href="index#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="indices" title="Index" rel="index">Index</a>]</p> </div><div class="_attribution">
+ <p class="_attribution-p">
+ &copy; Free Software Foundation<br>Licensed under the GNU Free Documentation License, Version 1.3.<br>
+ <a href="https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Name-lookup.html" class="_attribution-link">https://gcc.gnu.org/onlinedocs/gcc-13.1.0/gcc/Name-lookup.html</a>
+ </p>
+</div>