[cfe-commits] r98717 - /cfe/trunk/www/cxx_compatibility.html
John McCall
rjmccall at apple.com
Wed Mar 17 00:10:56 PDT 2010
Author: rjmccall
Date: Wed Mar 17 02:10:56 2010
New Revision: 98717
URL: http://llvm.org/viewvc/llvm-project?rev=98717&view=rev
Log:
Add another compatibility note and tweak a few of the existing ones.
Modified:
cfe/trunk/www/cxx_compatibility.html
Modified: cfe/trunk/www/cxx_compatibility.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_compatibility.html?rev=98717&r1=98716&r2=98717&view=diff
==============================================================================
--- cfe/trunk/www/cxx_compatibility.html (original)
+++ cfe/trunk/www/cxx_compatibility.html Wed Mar 17 02:10:56 2010
@@ -23,7 +23,8 @@
<li><a href="#intro">Introduction</a></li>
<li><a href="#vla">Variable-length arrays</a></li>
<li><a href="#init_static_const">Initialization of non-integral static const data members within a class definition</a></li>
-<li><a href="#dep_lookup">Dependent name lookup into dependent bases of class templates</a></li>
+<li><a href="#dep_lookup">Unqualified lookup in templates</a></li>
+<li><a href="#dep_lookup_bases">Unqualified lookup into dependent bases of class templates</a></li>
<li><a href="#default_init_const">Default initialization of const variable of a class type requires user-defined default constructor</a></li>
</ul>
@@ -97,87 +98,110 @@
const double SomeClass::SomeConstant<b> = 0.5</b>;
</pre>
+Note that the forthcoming C++0x standard will allow this.
+
<!-- ======================================================================= -->
-<h2 id="dep_lookup">Dependent name lookup into dependent bases of class templates</h2>
+<h2 id="dep_lookup">Unqualified lookup in templates</h2>
<!-- ======================================================================= -->
Some versions of GCC accept the following invalid code:
<pre>
-template <typename T>
-class Base {
- public:
- void DoThis(T x) {}
+template <typename T> struct Foo {
+ void Work(T x) {
+ func(x);
+ }
+};
+...
+void func(int x);
+...
+template struct Foo<int>; // or anything else that instantiates Foo<int>::Work
+</pre>
+
+The standard says that unqualified names like <tt>func</tt> are looked up
+when the template is defined, not when it's instantiated. Since
+<tt>void func(int)</tt> was not declared yet when <tt>Foo</tt> was
+defined, it's not considered. The fix is usually to
+declare <tt>func</tt> before <tt>Foo</tt>.
+<p>This is complicated by <i>argument-dependent lookup</i> (ADL),
+which is done when unqualified names are called as functions,
+like <tt>func(x)</tt> above. The standard says that ADL is performed
+in both places if any of the arguments are type-dependent, like
+<tt>x</tt> is in this example. However, ADL does nothing for builtin
+types like <tt>int</tt>, so the example is still invalid. See
+[basic.lookup.argdep] for more information.
+
+<!-- ======================================================================= -->
+<h2 id="dep_lookup_bases">Unqualified lookup into dependent bases of class templates</h2>
+<!-- ======================================================================= -->
+
+Some versions of GCC accept the following invalid code:
+
+<pre>
+template <typename T> struct Base {
+ void DoThis(T x) {}
static void DoThat(T x) {}
};
-template <typename T>
-class Derived : public Base<T> {
- public:
+template <typename T> struct Derived : public Base<T> {
void Work(T x) {
DoThis(x); // Invalid!
DoThat(x); // Invalid!
}
};
-
-void Test() {
- Derived<int> d;
- d.Work(42);
-}
</pre>
-Clang correctly rejects it with the following errors:
+Clang correctly rejects it with the following errors
+(when <tt>Derived</tt> is eventually instantiated):
<pre>
-my_file.cpp:13:5: error: use of undeclared identifier 'DoThis'
+my_file.cpp:8:5: error: use of undeclared identifier 'DoThis'
DoThis(x);
^
this->
-my_file.cpp:20:5: note: in instantiation of member function 'Derived<int>::Work' requested here
- d.Work(42);
- ^
-my_file.cpp:4:8: note: must qualify identifier to find this declaration in dependent base class
+my_file.cpp:2:8: note: must qualify identifier to find this declaration in dependent base class
void DoThis(T x) {}
^
-my_file.cpp:14:5: error: use of undeclared identifier 'DoThat'
+my_file.cpp:9:5: error: use of undeclared identifier 'DoThat'
DoThat(x);
^
this->
-my_file.cpp:6:15: note: must qualify identifier to find this declaration in dependent base class
+my_file.cpp:3:15: note: must qualify identifier to find this declaration in dependent base class
static void DoThat(T x) {}
</pre>
-The reason the code is invalid is that in
-class <tt>Derived<T></tt>, the base class type <tt>Base<T></tt>
-depends on the template argument <tt>T</tt> (hence it's called a dependent base
-class in C++ jargon), and C++ doesn't look at the members of a
-dependent base class when resolving unqualified calls like <tt>DoThis(x)</tt>
-and <tt>DoThat(x)</tt> (see [temp.dep] p3 for details). The fix, as Clang tells
-you, is to prefix the calls with <tt>this-></tt>:
+Like we said <a href="#dep_lookup">above</a>, unqualified names like
+<tt>DoThis</tt> and <tt>DoThat</tt> are looked up when the template
+<tt>Derived</tt> is defined, not when it's instantiated. When we look
+up a name used in a class, we usually look into the base classes.
+However, we can't look into the base class <tt>Base<T></tt>
+because its type depends on the template argument <tt>T</tt>, so the
+standard says we should just ignore it. See [temp.dep]p3 for details.
+
+<p>The fix, as Clang tells you, is to tell the compiler that we want a
+class member by prefixing the calls with <tt>this-></tt>:
<pre>
-...
-template <typename T>
-class Derived : public Base<T> {
- public:
void Work(T x) {
<b>this-></b>DoThis(x);
<b>this-></b>DoThat(x);
}
-};
-...
</pre>
-Alternatively, since DoThat() is a static method, you can also write
+Alternatively, you can tell the compiler exactly where to look:
<pre>
void Work(T x) {
- <b>this-></b>DoThis(x);
+ <b>Base<T></b>::DoThis(x);
<b>Base<T></b>::DoThat(x);
}
</pre>
+This works whether the methods are static or not, but be careful:
+if <tt>DoThis</tt> is virtual, calling it this way will bypass virtual
+dispatch!
+
<!-- ======================================================================= -->
<h2 id="default_init_const">Default initialization of const variable of a class type requires user-defined default constructor</h2>
<!-- ======================================================================= -->
More information about the cfe-commits
mailing list