implementation.htm 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  2. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml">
  4. <!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000, David Abrahams 2007 -->
  5. <!-- Distributed under the Boost -->
  6. <!-- Software License, Version 1.0. (See accompanying -->
  7. <!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
  8. <head>
  9. <meta name="generator" content=
  10. "HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
  11. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  12. <link rel="stylesheet" href="../../rst.css" type="text/css" />
  13. <title>Concept Checking Implementation</title>
  14. </head>
  15. <body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
  16. "#FF0000">
  17. <img src="../../boost.png" alt="C++ Boost" width="277" height=
  18. "86" /><br clear="none" />
  19. <h2><a name="warning" id="warning"><font color=
  20. "red">Warning</font></a></h2>
  21. <p><font color="red">This documentation is out-of-date; similar but
  22. newer implementation techniques are now used. This documentation
  23. also refers to components and protocols in the library's old
  24. interface such as <code>BOOST_CLASS_REQUIRES</code>
  25. and <code>constraints()</code> functions, which are still supported
  26. but deprecated.</font></p>
  27. <h2><a name="implementation" id="implementation">Implementation</a></h2>
  28. <p>Ideally we would like to catch, and indicate, the concept violation at
  29. the point of instantiation. As mentioned in D&amp;E[<a href=
  30. "bibliography.htm#stroustrup94:_design_evolution">2</a>], the error can be
  31. caught by exercising all of the requirements needed by the function
  32. template. Exactly how the requirements (the valid expressions in
  33. particular) are exercised is a tricky issue, since we want the code to be
  34. compiled—<i>but not executed</i>. Our approach is to exercise the
  35. requirements in a separate function that is assigned to a function pointer.
  36. In this case, the compiler will instantiate the function but will not
  37. actually invoke it. In addition, an optimizing compiler will remove the
  38. pointer assignment as ``dead code'' (though the run-time overhead added by
  39. the assignment would be trivial in any case). It might be conceivable for a
  40. compiler to skip the semantic analysis and compilation of the constraints
  41. function in the first place, which would make our function pointer
  42. technique ineffective. However, this is unlikely because removal of
  43. unnecessary code and functions is typically done in later stages of a
  44. compiler. We have successfully used the function pointer technique with GNU
  45. C++, Microsoft Visual C++, and several EDG-based compilers (KAI C++, SGI
  46. MIPSpro). The following code shows how this technique can be applied to the
  47. <tt>std::stable_sort()</tt> function:</p>
  48. <pre>
  49. template &lt;class RandomAccessIterator&gt;
  50. void stable_sort_constraints(RandomAccessIterator i)
  51. {
  52. typename std::iterator_traits&lt;RandomAccessIterator&gt;
  53. ::difference_type n;
  54. i += n; // exercise the requirements for RandomAccessIterator
  55. ...
  56. }
  57. template &lt;class RandomAccessIterator&gt;
  58. void stable_sort(RandomAccessIterator first, RandomAccessIterator last)
  59. {
  60. typedef void (*fptr_type)(RandomAccessIterator);
  61. fptr_type x = &amp;stable_sort_constraints;
  62. ...
  63. }
  64. </pre>
  65. <p>There is often a large set of requirements that need to be checked, and
  66. it would be cumbersome for the library implementor to write constraint
  67. functions like <tt>stable_sort_constraints()</tt> for every public
  68. function. Instead, we group sets of valid expressions together, according
  69. to the definitions of the corresponding concepts. For each concept we
  70. define a concept checking class template where the template parameter is
  71. for the type to be checked. The class contains a <tt>constraints()</tt>
  72. member function which exercises all of the valid expressions of the
  73. concept. The objects used in the constraints function, such as <tt>n</tt>
  74. and <tt>i</tt>, are declared as data members of the concept checking
  75. class.</p>
  76. <pre>
  77. template &lt;class Iter&gt;
  78. struct RandomAccessIteratorConcept
  79. {
  80. void constraints()
  81. {
  82. i += n;
  83. ...
  84. }
  85. typename std::iterator_traits&lt;RandomAccessIterator&gt;
  86. ::difference_type n;
  87. Iter i;
  88. ...
  89. };
  90. </pre>
  91. <p>We can still use the function pointer mechanism to cause instantiation
  92. of the constraints function, however now it will be a member function
  93. pointer. To make it easy for the library implementor to invoke the concept
  94. checks, we wrap the member function pointer mechanism in a function named
  95. <tt>function_requires()</tt>. The following code snippet shows how to use
  96. <tt>function_requires()</tt> to make sure that the iterator is a <a href=
  97. "http://www.boost.org/sgi/stl/RandomAccessIterator.html">RandomAccessIterator</a>.</p>
  98. <pre>
  99. template &lt;class Iter&gt;
  100. void stable_sort(Iter first, Iter last)
  101. {
  102. function_requires&lt; RandomAccessIteratorConcept&lt;Iter&gt; &gt;();
  103. ...
  104. }
  105. </pre>
  106. <p>The definition of the <tt>function_requires()</tt> is as follows. The
  107. <tt>Concept</tt> is the concept checking class that has been instantiated
  108. with the modeling type. We assign the address of the constraints member
  109. function to the function pointer <tt>x</tt>, which causes the instantiation
  110. of the constraints function and checking of the concept's valid
  111. expressions. We then assign <tt>x</tt> to <tt>x</tt> to avoid unused
  112. variable compiler warnings, and wrap everything in a do-while loop to
  113. prevent name collisions.</p>
  114. <pre>
  115. template &lt;class Concept&gt;
  116. void function_requires()
  117. {
  118. void (Concept::*x)() = BOOST_FPTR Concept::constraints;
  119. ignore_unused_variable_warning(x);
  120. }
  121. </pre>
  122. <p>To check the type parameters of class templates, we provide the
  123. <tt>BOOST_CLASS_REQUIRE</tt> macro which can be used inside the body of a
  124. class definition (whereas <tt>function_requires()</tt> can only be used
  125. inside of a function body). This macro declares a nested class template,
  126. where the template parameter is a function pointer. We then use the nested
  127. class type in a typedef with the function pointer type of the constraint
  128. function as the template argument. We use the <tt>type_var</tt> and
  129. <tt>concept</tt> names in the nested class and typedef names to help
  130. prevent name collisions.</p>
  131. <pre>
  132. #define BOOST_CLASS_REQUIRE(type_var, ns, concept) \
  133. typedef void (ns::concept &lt;type_var&gt;::* func##type_var##concept)(); \
  134. template &lt;func##type_var##concept _Tp1&gt; \
  135. struct concept_checking_##type_var##concept { }; \
  136. typedef concept_checking_##type_var##concept&lt; \
  137. BOOST_FPTR ns::concept&lt;type_var&gt;::constraints&gt; \
  138. concept_checking_typedef_##type_var##concept
  139. </pre>
  140. <p>In addition, there are versions of <tt>BOOST_CLASS_REQUIRE</tt> that
  141. take more arguments, to handle concepts that include interactions between
  142. two or more types. <tt>BOOST_CLASS_REQUIRE</tt> was not used in the
  143. implementation of the BCCL concept checks because some compilers do not
  144. implement template parameters of function pointer type.
  145. <!-- We decided not to go with this version since it is easier to misuse
  146. To check the type parameters of class templates, we provide the
  147. <tt>class_requires</tt> class which can be used inside the body of a
  148. class definition (whereas <tt>function_requires()</tt> can only be
  149. used inside of a function body). <tt>class_requires</tt> declares a
  150. nested class template, where the template parameter is a function
  151. pointer. We then use the nested class type in a typedef with the
  152. function pointer type of the constraint function as the template
  153. argument.
  154. <pre>
  155. template &lt;class Concept&gt;
  156. class class_requires
  157. {
  158. typedef void (Concept::* function_pointer)();
  159. template &lt;function_pointer Fptr&gt;
  160. struct dummy_struct { };
  161. public:
  162. typedef dummy_struct&lt; BOOST_FPTR Concept::constraints &gt; check;
  163. };
  164. </pre>
  165. <tt>class_requires</tt> was not used in the implementation of the
  166. Boost Concept Checking Library concept checks because several
  167. compilers do not implement template parameters of function pointer
  168. type.
  169. --></p>
  170. <p><a href="./reference.htm">Next: Reference</a><br />
  171. <a href="prog_with_concepts.htm">Prev: Programming With
  172. Concepts</a><br /></p>
  173. <hr />
  174. <table>
  175. <tr valign="top">
  176. <td nowrap="nowrap">Copyright &copy; 2000</td>
  177. <td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
  178. "mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
  179. Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
  180. 2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
  181. </tr>
  182. </table>
  183. </body>
  184. </html>