📄 name-lookup.html
字号:
<html lang="en"><head><title>Using the GNU Compiler Collection (GCC)</title><meta http-equiv="Content-Type" content="text/html"><meta name="description" content="Using the GNU Compiler Collection (GCC)"><meta name="generator" content="makeinfo 4.6"><!--Copyright © 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. <p>Permission is granted to copy, distribute and/or modify this documentunder the terms of the GNU Free Documentation License, Version 1.2 orany later version published by the Free Software Foundation; with theInvariant Sections being "GNU General Public License" and "FundingFree Software", the Front-Cover texts being (a) (see below), and withthe Back-Cover Texts being (b) (see below). A copy of the license isincluded in the section entitled "GNU Free Documentation License". <p>(a) The FSF's Front-Cover Text is: <p>A GNU Manual <p>(b) The FSF's Back-Cover Text is: <p>You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development.--><meta http-equiv="Content-Style-Type" content="text/css"><style type="text/css"><!-- pre.display { font-family:inherit } pre.format { font-family:inherit } pre.smalldisplay { font-family:inherit; font-size:smaller } pre.smallformat { font-family:inherit; font-size:smaller } pre.smallexample { font-size:smaller } pre.smalllisp { font-size:smaller }--></style></head><body><div class="node"><p>Node: <a name="Name%20lookup">Name lookup</a>,Next: <a rel="next" accesskey="n" href="Temporaries.html#Temporaries">Temporaries</a>,Previous: <a rel="previous" accesskey="p" href="Static-Definitions.html#Static%20Definitions">Static Definitions</a>,Up: <a rel="up" accesskey="u" href="C---Misunderstandings.html#C++%20Misunderstandings">C++ Misunderstandings</a><hr><br></div><h3 class="subsection">Name lookup, templates, and accessing members of base classes</h4><p>The C++ standard prescribes that all names that are not dependent ontemplate parameters are bound to their present definitions when parsinga template function or class.<a rel="footnote" href="#fn-1"><sup>1</sup></a> Only names that are dependent are looked up at the pointof instantiation. For example, consider<pre class="smallexample"> void foo(double); struct A { template <typename T> void f () { foo (1); // 1 int i = N; // 2 T t; t.bar(); // 3 foo (t); // 4 } static const int N; }; </pre> <p>Here, the names <code>foo</code> and <code>N</code> appear in a context that doesnot depend on the type of <code>T</code>. The compiler will thus require thatthey are defined in the context of use in the template, not only beforethe point of instantiation, and will here use <code>::foo(double)</code> and<code>A::N</code>, respectively. In particular, it will convert the integervalue to a <code>double</code> when passing it to <code>::foo(double)</code>. <p>Conversely, <code>bar</code> and the call to <code>foo</code> in the fourth markedline are used in contexts that do depend on the type of <code>T</code>, sothey are only looked up at the point of instantiation, and you canprovide declarations for them after declaring the template, but beforeinstantiating it. In particular, if you instantiate <code>A::f<int></code>,the last line will call an overloaded <code>::foo(int)</code> if one wasprovided, even if after the declaration of <code>struct A</code>. <p>This distinction between lookup of dependent and non-dependent names iscalled two-stage (or dependent) name lookup. G++ implements itsince version 3.4. <p>Two-stage name lookup sometimes leads to situations with behaviordifferent from non-template codes. The most common is probably this:<pre class="smallexample"> template <typename T> struct Base { int i; }; template <typename T> struct Derived : public Base<T> { int get_i() { return i; } }; </pre> <p>In <code>get_i()</code>, <code>i</code> is not used in a dependent context, so thecompiler 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>Base</code> even after declaring <code>Derived</code>, so the compiler can'treally know what <code>i</code> would refer to. If there is no globalvariable <code>i</code>, then you will get an error message. <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 baseclass is known. For this, you need to access <code>i</code> in a dependentcontext, by either using <code>this->i</code> (remember that <code>this</code> is oftype <code>Derived<T>*</code>, so is obviously dependent), or using<code>Base<T>::i</code>. Alternatively, <code>Base<T>::i</code> might be broughtinto scope by a <code>using</code>-declaration. <p>Another, similar example involves calling member functions of a baseclass:<pre class="smallexample"> template <typename T> struct Base { int f(); }; template <typename T> struct Derived : Base<T> { int g() { return f(); }; }; </pre> <p>Again, the call to <code>f()</code> is not dependent on template arguments(there are no arguments that depend on the type <code>T</code>, and it is alsonot otherwise specified that the call should be in a dependent context). Thus a global declaration of such a function must be available, sincethe one in the base class is not visible until instantiation time. Thecompiler will consequently produce the following error message:<pre class="smallexample"> x.cc: In member function `int Derived<T>::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> <p>To make the code valid either use <code>this->f()</code>, or<code>Base<T>::f()</code>. Using the <code>-fpermissive</code> flag will also letthe compiler accept the code, by marking all function calls for which nodeclaration is visible at the time of definition of the template forlater lookup at instantiation time, as if it were a dependent call. We do not recommend using <code>-fpermissive</code> to work around invalidcode, and it will also only catch cases where functions in base classesare called, not where variables in base classes are used (as in theexample above). <p>Note that some compilers (including G++ versions prior to 3.4) get theseexamples wrong and accept above code without an error. Those compilersdo not implement two-stage name lookup correctly. <div class="footnote"><hr><h4>Footnotes</h4><ol type="1"><li><a name="fn-1"></a><p>The C++ standard just uses theterm ``dependent'' for names that depend on the type or value oftemplate parameters. This shorter term will also be used in the rest ofthis section.</p> </ol><hr></div> </body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -