tti_func_templates.html 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
  4. <title>Introspecting Function Templates</title>
  5. <link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
  6. <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
  7. <link rel="home" href="../index.html" title="Chapter&#160;1.&#160;The Type Traits Introspection Library">
  8. <link rel="up" href="../index.html" title="Chapter&#160;1.&#160;The Type Traits Introspection Library">
  9. <link rel="prev" href="tti_usingMM.html" title="An example using the Macro Metafunctions">
  10. <link rel="next" href="../reference.html" title="Reference">
  11. </head>
  12. <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
  13. <table cellpadding="2" width="100%"><tr>
  14. <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
  15. <td align="center"><a href="../../../../../index.html">Home</a></td>
  16. <td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
  17. <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
  18. <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
  19. <td align="center"><a href="../../../../../more/index.htm">More</a></td>
  20. </tr></table>
  21. <hr>
  22. <div class="spirit-nav">
  23. <a accesskey="p" href="tti_usingMM.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../reference.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
  24. </div>
  25. <div class="section">
  26. <div class="titlepage"><div><div><h2 class="title" style="clear: both">
  27. <a name="the_type_traits_introspection_library.tti_func_templates"></a><a class="link" href="tti_func_templates.html" title="Introspecting Function Templates">Introspecting
  28. Function Templates</a>
  29. </h2></div></div></div>
  30. <p>
  31. The one nested element which the TTI library does not introspect is function
  32. templates.
  33. </p>
  34. <p>
  35. Function templates, like functions, can be member function templates or static
  36. member function templates. In this respect they are related to functions. Function
  37. templates represent a family of possible functions. In this respect they are
  38. similar to class templates, which represent a family of possible class types.
  39. </p>
  40. <p>
  41. The technique for introspecting class templates in the TTI library is taken
  42. from the implementation of the technique in the Boost MPL library. In the case
  43. of <code class="computeroutput"><span class="identifier">BOOST_TTI_HAS_TEMPLATE</span></code> it
  44. directly uses the Boost MPL library functionality while in the case of <code class="computeroutput"><span class="identifier">BOOST_TTI_HAS_TEMPLATE_CHECK_PARAMS</span></code> it replicates
  45. much of the technique in the Boost MPL library. The technique depends directly
  46. on the fact that in C++ we can pass a template as a parameter to another template
  47. using what is called a "template template" parameter type.
  48. </p>
  49. <p>
  50. One obvious thing about a template template parameter type is that it is a
  51. class template. For whatever historical or technical reasons, no one has ever
  52. proposed that C++ have a way of passing a function template directly as a template
  53. parameter, perhaps to be called a "function template template" parameter
  54. type. I personally think this would be a good addition to C++ and would make
  55. the ability of passing a template as a parameter to another template more orthogonal,
  56. since both class templates and function templates would be supported. My efforts
  57. to discuss this on the major C++ newsgroups have met with arguments both against
  58. its practical usage and the justification that one can pass a function template
  59. to another template nested in a non-template class, which serves as a type.
  60. But of course we can do the same thing with class templates, which is in fact
  61. what Boost MPL does to pass templates as metadata, yet we still have template
  62. template parameters as class templates.
  63. </p>
  64. <p>
  65. Nonetheless the fact that we can pass class templates as a template parameter
  66. but not function templates as a template parameter is the major factor why
  67. there is no really good method for introspecting function templates at compile
  68. time.
  69. </p>
  70. <h4>
  71. <a name="the_type_traits_introspection_library.tti_func_templates.h0"></a>
  72. <span class="phrase"><a name="the_type_traits_introspection_library.tti_func_templates.instantiating_a_nested_function_template"></a></span><a class="link" href="tti_func_templates.html#the_type_traits_introspection_library.tti_func_templates.instantiating_a_nested_function_template">Instantiating
  73. a nested function template</a>
  74. </h4>
  75. <p>
  76. There is, however, an alternate but less certain way of introspecting a function
  77. template. I will endeavor to explain why this way is not currently included
  78. in the TTI library, but first I will explain what it is.
  79. </p>
  80. <p>
  81. It is possible to check whether some particular <span class="bold"><strong>instantiation</strong></span>
  82. of a nested function template exists at compile-time without generating a compiler
  83. error. Although checking if some particular instantiation of a nested function
  84. template exists at compile-time does not prove that the nested function template
  85. itself does or does not exist, since the instantiation itself may be incorrect
  86. and fail even when the nested function template exists, it provides a partial,
  87. if flawed, means of checking.
  88. </p>
  89. <p>
  90. The code to do this for member function templates looks like this ( similar
  91. code also exists for static member function templates ):
  92. </p>
  93. <pre class="programlisting"><span class="keyword">template</span>
  94. <span class="special">&lt;</span>
  95. <span class="keyword">class</span> <span class="identifier">C</span><span class="special">,</span>
  96. <span class="keyword">class</span> <span class="identifier">T</span>
  97. <span class="special">&gt;</span>
  98. <span class="keyword">struct</span> <span class="identifier">TestFunctionTemplate</span>
  99. <span class="special">{</span>
  100. <span class="keyword">typedef</span> <span class="keyword">char</span> <span class="identifier">Bad</span><span class="special">;</span>
  101. <span class="keyword">struct</span> <span class="identifier">Good</span> <span class="special">{</span> <span class="keyword">char</span> <span class="identifier">x</span><span class="special">[</span><span class="number">2</span><span class="special">];</span> <span class="special">};</span>
  102. <span class="keyword">template</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">helper</span><span class="special">;</span>
  103. <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">static</span> <span class="identifier">Good</span> <span class="identifier">check</span><span class="special">(</span><span class="identifier">helper</span><span class="special">&lt;&amp;</span><span class="identifier">U</span><span class="special">::</span><span class="keyword">template</span> <span class="identifier">SomeFuncTemplateName</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">long</span><span class="special">,</span><span class="keyword">double</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">*);</span>
  104. <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">static</span> <span class="identifier">Bad</span> <span class="identifier">check</span><span class="special">(...);</span>
  105. <span class="keyword">static</span> <span class="keyword">const</span> <span class="keyword">bool</span> <span class="identifier">value</span><span class="special">=</span><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">check</span><span class="special">&lt;</span><span class="identifier">C</span><span class="special">&gt;(</span><span class="number">0</span><span class="special">))==</span><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">Good</span><span class="special">);</span>
  106. <span class="special">};</span>
  107. </pre>
  108. <p>
  109. where 'SomeFuncTemplateName' is the name of the nested function template, followed
  110. by some parameters to instantiate it. The 'class C' is the type of the enclosing
  111. class and the 'class T' is the type of the instantiated member function template
  112. as a member function.
  113. </p>
  114. <p>
  115. As an example if we had:
  116. </p>
  117. <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">AType</span>
  118. <span class="special">{</span>
  119. <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">X</span><span class="special">,</span><span class="keyword">class</span> <span class="identifier">Y</span><span class="special">,</span><span class="keyword">class</span> <span class="identifier">Z</span><span class="special">&gt;</span> <span class="keyword">double</span> <span class="identifier">SomeFuncTemplateName</span><span class="special">(</span><span class="identifier">X</span><span class="special">,</span><span class="identifier">Y</span> <span class="special">*,</span><span class="identifier">Z</span> <span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="number">0.0</span><span class="special">;</span> <span class="special">}</span>
  120. <span class="special">};</span>
  121. </pre>
  122. <p>
  123. then instantiating the above template with:
  124. </p>
  125. <pre class="programlisting"><span class="identifier">TestFunctionTemplate</span>
  126. <span class="special">&lt;</span>
  127. <span class="identifier">AType</span><span class="special">,</span>
  128. <span class="keyword">double</span> <span class="special">(</span><span class="identifier">AType</span><span class="special">::*)(</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">long</span> <span class="special">*,</span><span class="keyword">double</span> <span class="special">&amp;)</span>
  129. <span class="special">&gt;</span>
  130. </pre>
  131. <p>
  132. would provide a compile-time boolean value which would tell us whether the
  133. nested member function template exists for the particular instantiation provided
  134. above. Furthermore, through the use of a macro, the TTI library could provide
  135. the means for specifying the name of the nested member function template ('SomeFuncTemplateName'
  136. above) and its set of instantiated parameters ('int,long,double' above) for
  137. generating the template.
  138. </p>
  139. <p>
  140. So why does not the TTI library not provide at least this much functionality
  141. for introspecting member function templates, even if it represents a partially
  142. flawed way of doing so ?
  143. </p>
  144. <p>
  145. The reason is stunningly disappointing. Although the above code is perfectly
  146. correct C++ code ( 'clang' works correctly ), two of the major C++ compilers,
  147. in all of their different releases, can not handle the above code correctly.
  148. Both gcc ( g++ ) and Visual C++ incorrectly choose the wrong 'check' function
  149. even when the correct 'check' function applies ( Comeau C++ also fails but
  150. I am less concerned about that compiler since it is not used nearly as much
  151. as the other two ). All my attempts at alternatives to the above code have
  152. also failed. The problems with both compilers, in this regard, can be seen
  153. more easily with this snippet:
  154. </p>
  155. <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">AType</span>
  156. <span class="special">{</span>
  157. <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">AA</span><span class="special">&gt;</span> <span class="keyword">void</span> <span class="identifier">SomeFuncTemplate</span><span class="special">()</span> <span class="special">{</span> <span class="special">}</span>
  158. <span class="special">};</span>
  159. <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
  160. <span class="keyword">struct</span> <span class="identifier">Test</span>
  161. <span class="special">{</span>
  162. <span class="keyword">template</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">helper</span><span class="special">;</span>
  163. <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">check</span><span class="special">(</span><span class="identifier">helper</span><span class="special">&lt;&amp;</span><span class="identifier">U</span><span class="special">::</span><span class="keyword">template</span> <span class="identifier">SomeFuncTemplate</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">*)</span> <span class="special">{</span> <span class="special">}</span>
  164. <span class="special">};</span>
  165. <span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
  166. <span class="special">{</span>
  167. <span class="identifier">Test</span><span class="special">&lt;</span> <span class="keyword">void</span> <span class="special">(</span><span class="identifier">AType</span><span class="special">::*)()</span> <span class="special">&gt;::</span><span class="identifier">check</span><span class="special">&lt;</span><span class="identifier">AType</span><span class="special">&gt;(</span><span class="number">0</span><span class="special">);</span>
  168. <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
  169. <span class="special">}</span>
  170. </pre>
  171. <p>
  172. Both compilers report compile errors with this perfectly correct code,
  173. </p>
  174. <p>
  175. gcc:
  176. </p>
  177. <pre class="programlisting"><span class="identifier">error</span><span class="special">:</span> <span class="identifier">no</span> <span class="identifier">matching</span> <span class="identifier">function</span> <span class="keyword">for</span> <span class="identifier">call</span> <span class="identifier">to</span> <span class="char">'Test&lt;void (AType::*)()&gt;::check(int)'</span>
  178. </pre>
  179. <p>
  180. and msvc:
  181. </p>
  182. <pre class="programlisting"><span class="identifier">error</span> <span class="identifier">C2770</span><span class="special">:</span> <span class="identifier">invalid</span> <span class="keyword">explicit</span> <span class="keyword">template</span> <span class="identifier">argument</span><span class="special">(</span><span class="identifier">s</span><span class="special">)</span> <span class="keyword">for</span> <span class="char">'void Test&lt;T&gt;::check(Test&lt;T&gt;::helper&lt;&amp;U::SomeFuncTemplate&lt;int&gt;&gt; *)'</span>
  183. </pre>
  184. <p>
  185. There is a workaround for these compiler problems, which is to hardcode the
  186. name of the enclosing class, via a macro, in the generated template rather
  187. than pass it as a template type. In that case both compilers can handle both
  188. the member function code and the code snippet above correctly. In essence,
  189. when the line:
  190. </p>
  191. <pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">check</span><span class="special">(</span><span class="identifier">helper</span><span class="special">&lt;&amp;</span><span class="identifier">U</span><span class="special">::</span><span class="keyword">template</span> <span class="identifier">SomeFuncTemplate</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">*)</span> <span class="special">{</span> <span class="special">}</span>
  192. </pre>
  193. <p>
  194. gets replaced by:
  195. </p>
  196. <pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">check</span><span class="special">(</span><span class="identifier">helper</span><span class="special">&lt;&amp;</span><span class="identifier">AType</span><span class="special">::</span><span class="keyword">template</span> <span class="identifier">SomeFuncTemplate</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="special">*)</span> <span class="special">{</span> <span class="special">}</span>
  197. </pre>
  198. <p>
  199. both gcc and Visual C++ work correctly. The same goes for the 'check' line
  200. in the 'TestFunctionTemplate' above.
  201. </p>
  202. <p>
  203. But the workaround destroys one of the basic tenets of the TTI library, which
  204. is that the enclosing class be passed as a template parameter, especially as
  205. the enclosing class need not actually exist ( see <code class="computeroutput"><span class="identifier">BOOST_TTI_MEMBER_TYPE</span></code>
  206. and the previous discussion of 'Nested Types' ), without producing a compiler
  207. error. So I have decided not to implement even this methodology to introspect
  208. nested function templates in the TTI library.
  209. </p>
  210. </div>
  211. <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
  212. <td align="left"></td>
  213. <td align="right"><div class="copyright-footer">Copyright &#169; 2011-2013 Tropic Software
  214. East Inc<p>
  215. Distributed under the Boost Software License, Version 1.0. (See accompanying
  216. file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
  217. </p>
  218. </div></td>
  219. </tr></table>
  220. <hr>
  221. <div class="spirit-nav">
  222. <a accesskey="p" href="tti_usingMM.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../reference.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
  223. </div>
  224. </body>
  225. </html>