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