[cfe-commits] r106068 - in /cfe/trunk/www: content.css cxx_compatibility.html

Jeffrey Yasskin jyasskin at google.com
Tue Jun 15 16:50:08 PDT 2010


Author: jyasskin
Date: Tue Jun 15 18:50:08 2010
New Revision: 106068

URL: http://llvm.org/viewvc/llvm-project?rev=106068&view=rev
Log:
Describe a gcc compatibility problem that occurs when a template calls a
function defined between its declaration and an instantiation, and that
function isn't findable through ADL.

Modified:
    cfe/trunk/www/content.css
    cfe/trunk/www/cxx_compatibility.html

Modified: cfe/trunk/www/content.css
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/content.css?rev=106068&r1=106067&r2=106068&view=diff
==============================================================================
--- cfe/trunk/www/content.css (original)
+++ cfe/trunk/www/content.css Tue Jun 15 18:50:08 2010
@@ -23,5 +23,8 @@
 
 .itemTitle { color:#2d58b7 }
 
+span.error { color:red }
+span.caret { color:green; font-weight:bold }
+
 /* Tables */
 tr { vertical-align:top }

Modified: cfe/trunk/www/cxx_compatibility.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_compatibility.html?rev=106068&r1=106067&r2=106068&view=diff
==============================================================================
--- cfe/trunk/www/cxx_compatibility.html (original)
+++ cfe/trunk/www/cxx_compatibility.html Tue Jun 15 18:50:08 2010
@@ -25,6 +25,7 @@
 <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>
@@ -216,6 +217,129 @@
 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 <iostream>
+#include <utility>
+#include <vector>
+
+template<typename T>
+void Dump(const T& value) {
+  std::cout << value << "\n";
+}
+
+template<typename T, typename U>
+std::ostream& operator<<(std::ostream& out, const std::pair<T, U>& i) {
+  return out << '(' << i.first << ", " << i.second << ")";
+}
+
+namespace ns {
+  struct Data {};
+}
+
+std::ostream& operator<<(std::ostream& out, ns::Data) {
+  return out << "Some data";
+}
+
+void Use() {
+  Dump(std::make_pair(3, 4.5));
+  Dump(ns::Data());
+  Dump(std::vector<const char*>(1, "Hello World"));
+}
+
+template<typename T>
+std::ostream& operator<<(std::ostream& out, const std::vector<T>& vec) {
+  out << '[';
+  for (size_t i = 0, size = vec.size(); i != size; ++i) {
+    if (i != 0)
+      out << ", ";
+    out << vec[i];
+  }
+  return out << ']';
+}
+</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<char>') and 'std::pair<int, double> const')</b>
+  std::cout << value << "\n";
+  <span class=caret>~~~~~~~~~ ^  ~~~~~</span>
+<b>test.cc:24:3: note:</b> in instantiation of function template specialization 'Dump<std::pair<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<char>') and 'ns::Data const')</b>
+  std::cout << value << "\n";
+  <span class=caret>~~~~~~~~~ ^  ~~~~~</span>
+<b>test.cc:25:3: note:</b> in instantiation of function template specialization 'Dump<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<char>') and 'std::vector<char const *, std::allocator<char const *> > const')</b>
+  std::cout << value << "\n";
+  <span class=caret>~~~~~~~~~ ^  ~~~~~</span>
+<b>test.cc:26:3: note:</b> in instantiation of function template specialization 'Dump<std::vector<char const *, std::allocator<char const *> > >' requested here
+  Dump(std::vector<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 <iostream>
+#include <utility>
+#include <vector>
+
+template<typename T>  // Fix 1.
+std::ostream& operator<<(std::ostream& out, const std::vector<T>& vec);
+
+template<typename T, typename U>  // Fix 2.
+std::ostream& operator<<(std::ostream& out, const std::pair<T, U>& i) {
+  return out << '(' << i.first << ", " << i.second << ")";
+}
+
+template<typename T>
+void Dump(const T& value) {
+  std::cout << value << "\n";
+}
+
+namespace ns {
+  struct Data {};
+  std::ostream& operator<<(std::ostream& out, Data) {  // Fix 3.
+    return out << "Some data";
+  }
+}
+
+void Use() {
+  Dump(std::make_pair(3, 4.5));
+  Dump(ns::Data());
+  Dump(std::vector<const char*>(1, "Hello World"));
+}
+
+template<typename T>
+std::ostream& operator<<(std::ostream& out, const std::vector<T>& vec) {
+  out << '[';
+  for (size_t i = 0, size = vec.size(); i != size; ++i) {
+    if (i != 0)
+      out << ", ";
+    out << vec[i];
+  }
+  return out << ']';
+}
+</pre>
+
+<!-- ======================================================================= -->
 <h2 id="undep_incomplete">Incomplete types in templates</h2>
 <!-- ======================================================================= -->
 





More information about the cfe-commits mailing list