summaryrefslogtreecommitdiffstats
path: root/www/cxx_compatibility.html
diff options
context:
space:
mode:
authorJeffrey Yasskin <jyasskin@google.com>2010-06-15 23:50:08 +0000
committerJeffrey Yasskin <jyasskin@google.com>2010-06-15 23:50:08 +0000
commit1390c3d43d0f4eb98be65176cafbf38c1fcbe2b0 (patch)
tree35c0618bbb2be617d4baf8eafa4aad63c82e17ab /www/cxx_compatibility.html
parent2a71107b9a0aa647c18e7655c53d9940ab390963 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106068 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'www/cxx_compatibility.html')
-rw-r--r--www/cxx_compatibility.html124
1 files changed, 124 insertions, 0 deletions
diff --git a/www/cxx_compatibility.html b/www/cxx_compatibility.html
index 02dabbe8e3..27defc2d8a 100644
--- a/www/cxx_compatibility.html
+++ b/www/cxx_compatibility.html
@@ -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 @@ 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>
<!-- ======================================================================= -->