]> granicus.if.org Git - clang/commitdiff
Fix template ordering compatibility docs. I missed another section that covered
authorJeffrey Yasskin <jyasskin@google.com>
Wed, 16 Jun 2010 01:12:12 +0000 (01:12 +0000)
committerJeffrey Yasskin <jyasskin@google.com>
Wed, 16 Jun 2010 01:12:12 +0000 (01:12 +0000)
the same thing.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106076 91177308-0d34-0410-b5e6-96231b3b80d8

www/cxx_compatibility.html

index 27defc2d8ac13f6f6434282732074157e63a5a1a..46e3a9f909146f43d629647c949ed963e78f0678 100644 (file)
@@ -25,7 +25,6 @@
 <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">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="#declaration_ordering">Template uses of a function must either find the function by ADL or come after the declaration of the function</a></li>
 <li><a href="#undep_incomplete">Incomplete types in templates</a></li>
 <li><a href="#bad_templates">Templates with no valid instantiations</a></li>
 <li><a href="#default_init_const">Default initialization of const variable of a class type requires user-defined default constructor</a></li>
@@ -118,33 +117,103 @@ Note that the forthcoming C++0x standard will allow this.
 <h2 id="dep_lookup">Unqualified lookup in templates</h2>
 <!-- ======================================================================= -->
 
-Some versions of GCC accept the following invalid code:
+<p>Some versions of GCC accept the following invalid code:
 
 <pre>
-template &lt;typename T&gt; struct Foo {
-  void Work(T x) {
-    func(x);
-  }
-};
-...
-void func(int x);
-...
-template struct Foo&lt;int&gt;; // or anything else that instantiates Foo&lt;int&gt;::Work
+#include &lt;iostream>
+#include &lt;utility>
+
+template&lt;typename T>
+void Dump(const T& value) {
+  std::cout &lt;&lt; value &lt;&lt; "\n";
+}
+
+namespace ns {
+  struct Data {};
+}
+
+std::ostream& operator&lt;&lt;(std::ostream& out, ns::Data) {
+  return out &lt;&lt; "Some data";
+}
+
+void Use() {
+  Dump(std::make_pair(3, 4.5));
+  Dump(ns::Data());
+}
+
+template&lt;typename T, typename U>
+std::ostream& operator&lt;&lt;(std::ostream& out, const std::pair&lt;T, U>& p) {
+  return out &lt;&lt; '(' &lt;&lt; p.first &lt;&lt; ", " &lt;&lt; p.second &lt;&lt; ")";
+}
 </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>Clang complains:</p>
+
+<pre>
+<b>test.cc:6:13: <span class=error>error:</span> invalid operands to binary expression ('ostream' (aka 'basic_ostream&lt;char>') and 'std::pair&lt;int, double> const')</b>
+  std::cout &lt;&lt; value &lt;&lt; "\n";
+  <span class=caret>~~~~~~~~~ ^  ~~~~~</span>
+<b>test.cc:18:3: note:</b> in instantiation of function template specialization 'Dump&lt;std::pair&lt;int, double> >' requested here
+  Dump(std::make_pair(3, 4.5));
+  <span class=caret>^</span>
+<b>test.cc:6:13: <span class=error>error:</span> invalid operands to binary expression ('ostream' (aka 'basic_ostream&lt;char>') and 'ns::Data const')</b>
+  std::cout &lt;&lt; value &lt;&lt; "\n";
+  <span class=caret>~~~~~~~~~ ^  ~~~~~</span>
+<b>test.cc:19:3: note:</b> in instantiation of function template specialization 'Dump&lt;ns::Data>' requested here
+  Dump(ns::Data());
+  <span class=caret>^</span>
+2 errors generated.
+</pre>
+
+<p>The standard, in [temp.dep.candidate], says that unqualified names
+like <tt>operator&lt;&lt;</tt> are looked up when the template is
+defined, not when it's instantiated. Since
+<tt>operator&lt;&lt;(std::ostream&, const std::pair&lt;>&)</tt>
+and <tt>operator&lt;&lt;(std::ostream&, ns::Data)</tt> were not
+declared yet when <tt>Dump</tt> was defined, they're not considered.
 
 <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.
+like <tt>operator&lt;&lt;</tt> above.  The standard says that ADL is
+performed in both places if any of the arguments are type-dependent,
+like <tt>value</tt> and <tt>p</tt> are in this example.
+
+<p>The fix is usually to</p>
+<ol><li>Add a declaration before the use of the function,
+<li>Move the definition to before the use of the function, or
+<li>Move the function into the same namespace as one of its arguments
+so that ADL applies.  (Note that it still needs to be declared before
+the template is <i>instantiated</i>, and that ADL doesn't apply to
+built-in types.)
+</ol>
+
+<pre>
+#include &lt;iostream>
+#include &lt;utility>
+
+template&lt;typename T, typename U>  // Fix 2
+std::ostream& operator&lt;&lt;(std::ostream& out, const std::pair&lt;T, U>& p) {
+  return out &lt;&lt; '(' &lt;&lt; p.first &lt;&lt; ", " &lt;&lt; p.second &lt;&lt; ")";
+}
+
+template&lt;typename T>
+void Dump(const T& value) {
+  std::cout &lt;&lt; value &lt;&lt; "\n";
+}
+
+namespace ns {
+  struct Data {};
+
+  std::ostream& operator&lt;&lt;(std::ostream& out, Data) {  // Fix 3
+    return out &lt;&lt; "Some data";
+  }
+}
+
+void Use() {
+  Dump(std::make_pair(3, 4.5));
+  Dump(ns::Data());
+}
+</pre>
 
 <!-- ======================================================================= -->
 <h2 id="dep_lookup_bases">Unqualified lookup into dependent bases of class templates</h2>
@@ -216,129 +285,6 @@ 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="declaration_ordering">Template uses of a function must either find the function by ADL or come after the declaration of the function</h2>
-<!-- ======================================================================= -->
-
-<p>For example, gcc-4.4 accepts the following code:</p>
-
-<pre>
-#include &lt;iostream>
-#include &lt;utility>
-#include &lt;vector>
-
-template&lt;typename T>
-void Dump(const T& value) {
-  std::cout &lt;&lt; value &lt;&lt; "\n";
-}
-
-template&lt;typename T, typename U>
-std::ostream& operator&lt;&lt;(std::ostream& out, const std::pair&lt;T, U>& i) {
-  return out &lt;&lt; '(' &lt;&lt; i.first &lt;&lt; ", " &lt;&lt; i.second &lt;&lt; ")";
-}
-
-namespace ns {
-  struct Data {};
-}
-
-std::ostream& operator&lt;&lt;(std::ostream& out, ns::Data) {
-  return out &lt;&lt; "Some data";
-}
-
-void Use() {
-  Dump(std::make_pair(3, 4.5));
-  Dump(ns::Data());
-  Dump(std::vector&lt;const char*>(1, "Hello World"));
-}
-
-template&lt;typename T>
-std::ostream& operator&lt;&lt;(std::ostream& out, const std::vector&lt;T>& vec) {
-  out &lt;&lt; '[';
-  for (size_t i = 0, size = vec.size(); i != size; ++i) {
-    if (i != 0)
-      out &lt;&lt; ", ";
-    out &lt;&lt; vec[i];
-  }
-  return out &lt;&lt; ']';
-}
-</pre>
-
-<p>while clang, following the rules in <tt>[temp.dep.candidate]</tt>
-complains:</p>
-
-<pre>
-<b>test.cc:7:13: <span class=error>error:</span> invalid operands to binary expression ('ostream' (aka 'basic_ostream&lt;char>') and 'std::pair&lt;int, double> const')</b>
-  std::cout &lt;&lt; value &lt;&lt; "\n";
-  <span class=caret>~~~~~~~~~ ^  ~~~~~</span>
-<b>test.cc:24:3: note:</b> in instantiation of function template specialization 'Dump&lt;std::pair&lt;int, double> >' requested here
-  Dump(std::make_pair(3, 4.5));
-  <span class=caret>^</span>
-<b>test.cc:7:13: <span class=error>error:</span> invalid operands to binary expression ('ostream' (aka 'basic_ostream&lt;char>') and 'ns::Data const')</b>
-  std::cout &lt;&lt; value &lt;&lt; "\n";
-  <span class=caret>~~~~~~~~~ ^  ~~~~~</span>
-<b>test.cc:25:3: note:</b> in instantiation of function template specialization 'Dump&lt;ns::Data>' requested here
-  Dump(ns::Data());
-  <span class=caret>^</span>
-<b>test.cc:7:13: <span class=error>error:</span> invalid operands to binary expression ('ostream' (aka 'basic_ostream&lt;char>') and 'std::vector&lt;char const *, std::allocator&lt;char const *> > const')</b>
-  std::cout &lt;&lt; value &lt;&lt; "\n";
-  <span class=caret>~~~~~~~~~ ^  ~~~~~</span>
-<b>test.cc:26:3: note:</b> in instantiation of function template specialization 'Dump&lt;std::vector&lt;char const *, std::allocator&lt;char const *> > >' requested here
-  Dump(std::vector&lt;const char*>(1, "Hello World"));
-  <span class=caret>^</span>
-3 errors generated.
-</pre>
-
-<p>The fix is to</p>
-<ol><li>Add a declaration before the use of the function, or
-<li>Move the definition to before the use of the function, or
-<li>Move the function into the same namespace as one of its
-arguments. (Note that it still needs to be declared before the
-template is <i>instantiated</i>.)
-</ol>
-
-<pre>
-#include &lt;iostream>
-#include &lt;utility>
-#include &lt;vector>
-
-template&lt;typename T>  // Fix 1.
-std::ostream& operator&lt;&lt;(std::ostream& out, const std::vector&lt;T>& vec);
-
-template&lt;typename T, typename U>  // Fix 2.
-std::ostream& operator&lt;&lt;(std::ostream& out, const std::pair&lt;T, U>& i) {
-  return out &lt;&lt; '(' &lt;&lt; i.first &lt;&lt; ", " &lt;&lt; i.second &lt;&lt; ")";
-}
-
-template&lt;typename T>
-void Dump(const T& value) {
-  std::cout &lt;&lt; value &lt;&lt; "\n";
-}
-
-namespace ns {
-  struct Data {};
-  std::ostream& operator&lt;&lt;(std::ostream& out, Data) {  // Fix 3.
-    return out &lt;&lt; "Some data";
-  }
-}
-
-void Use() {
-  Dump(std::make_pair(3, 4.5));
-  Dump(ns::Data());
-  Dump(std::vector&lt;const char*>(1, "Hello World"));
-}
-
-template&lt;typename T>
-std::ostream& operator&lt;&lt;(std::ostream& out, const std::vector&lt;T>& vec) {
-  out &lt;&lt; '[';
-  for (size_t i = 0, size = vec.size(); i != size; ++i) {
-    if (i != 0)
-      out &lt;&lt; ", ";
-    out &lt;&lt; vec[i];
-  }
-  return out &lt;&lt; ']';
-}
-</pre>
-
 <!-- ======================================================================= -->
 <h2 id="undep_incomplete">Incomplete types in templates</h2>
 <!-- ======================================================================= -->