| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |
| "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| |
| <html xmlns="http://www.w3.org/1999/xhtml"> |
| <!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000, David Abrahams 2007 --> |
| <!-- Distributed under the Boost --> |
| <!-- Software License, Version 1.0. (See accompanying --> |
| <!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) --> |
| |
| <head> |
| <meta name="generator" content= |
| "HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" /> |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
| <link rel="stylesheet" href="../../rst.css" type="text/css" /> |
| |
| <title>Concept Checking Implementation</title> |
| </head> |
| |
| <body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink= |
| "#FF0000"> |
| <img src="../../boost.png" alt="C++ Boost" width="277" height= |
| "86" /><br clear="none" /> |
| |
| <h2><a name="warning" id="warning"><font color= |
| "red">Warning</font></a></h2> |
| |
| <p><font color="red">This documentation is out-of-date; similar but |
| newer implementation techniques are now used. This documentation |
| also refers to components and protocols in the library's old |
| interace such as <code>BOOST_CLASS_REQUIRES</code> |
| and <code>constraints()</code> functions, which are still supported |
| but deprecated.</font></p> |
| |
| <h2><a name="implementation" id="implementation">Implementation</a></h2> |
| |
| <p>Ideally we would like to catch, and indicate, the concept violation at |
| the point of instantiation. As mentioned in D&E[<a href= |
| "bibliography.htm#stroustrup94:_design_evolution">2</a>], the error can be |
| caught by exercising all of the requirements needed by the function |
| template. Exactly how the requirements (the valid expressions in |
| particular) are exercised is a tricky issue, since we want the code to be |
| compiled—<i>but not executed</i>. Our approach is to exercise the |
| requirements in a separate function that is assigned to a function pointer. |
| In this case, the compiler will instantiate the function but will not |
| actually invoke it. In addition, an optimizing compiler will remove the |
| pointer assignment as ``dead code'' (though the run-time overhead added by |
| the assignment would be trivial in any case). It might be conceivable for a |
| compiler to skip the semantic analysis and compilation of the constraints |
| function in the first place, which would make our function pointer |
| technique ineffective. However, this is unlikely because removal of |
| unnecessary code and functions is typically done in later stages of a |
| compiler. We have successfully used the function pointer technique with GNU |
| C++, Microsoft Visual C++, and several EDG-based compilers (KAI C++, SGI |
| MIPSpro). The following code shows how this technique can be applied to the |
| <tt>std::stable_sort()</tt> function:</p> |
| <pre> |
| template <class RandomAccessIterator> |
| void stable_sort_constraints(RandomAccessIterator i) |
| { |
| typename std::iterator_traits<RandomAccessIterator> |
| ::difference_type n; |
| i += n; // exercise the requirements for RandomAccessIterator |
| ... |
| } |
| template <class RandomAccessIterator> |
| void stable_sort(RandomAccessIterator first, RandomAccessIterator last) |
| { |
| typedef void (*fptr_type)(RandomAccessIterator); |
| fptr_type x = &stable_sort_constraints; |
| ... |
| } |
| </pre> |
| |
| <p>There is often a large set of requirements that need to be checked, and |
| it would be cumbersome for the library implementor to write constraint |
| functions like <tt>stable_sort_constraints()</tt> for every public |
| function. Instead, we group sets of valid expressions together, according |
| to the definitions of the corresponding concepts. For each concept we |
| define a concept checking class template where the template parameter is |
| for the type to be checked. The class contains a <tt>contraints()</tt> |
| member function which exercises all of the valid expressions of the |
| concept. The objects used in the constraints function, such as <tt>n</tt> |
| and <tt>i</tt>, are declared as data members of the concept checking |
| class.</p> |
| <pre> |
| template <class Iter> |
| struct RandomAccessIteratorConcept |
| { |
| void constraints() |
| { |
| i += n; |
| ... |
| } |
| typename std::iterator_traits<RandomAccessIterator> |
| ::difference_type n; |
| Iter i; |
| ... |
| }; |
| </pre> |
| |
| <p>We can still use the function pointer mechanism to cause instantiation |
| of the constraints function, however now it will be a member function |
| pointer. To make it easy for the library implementor to invoke the concept |
| checks, we wrap the member function pointer mechanism in a function named |
| <tt>function_requires()</tt>. The following code snippet shows how to use |
| <tt>function_requires()</tt> to make sure that the iterator is a <a href= |
| "http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>.</p> |
| <pre> |
| template <class Iter> |
| void stable_sort(Iter first, Iter last) |
| { |
| function_requires< RandomAccessIteratorConcept<Iter> >(); |
| ... |
| } |
| </pre> |
| |
| <p>The definition of the <tt>function_requires()</tt> is as follows. The |
| <tt>Concept</tt> is the concept checking class that has been instantiated |
| with the modeling type. We assign the address of the constraints member |
| function to the function pointer <tt>x</tt>, which causes the instantiation |
| of the constraints function and checking of the concept's valid |
| expressions. We then assign <tt>x</tt> to <tt>x</tt> to avoid unused |
| variable compiler warnings, and wrap everything in a do-while loop to |
| prevent name collisions.</p> |
| <pre> |
| template <class Concept> |
| void function_requires() |
| { |
| void (Concept::*x)() = BOOST_FPTR Concept::constraints; |
| ignore_unused_variable_warning(x); |
| } |
| </pre> |
| |
| <p>To check the type parameters of class templates, we provide the |
| <tt>BOOST_CLASS_REQUIRE</tt> macro which can be used inside the body of a |
| class definition (whereas <tt>function_requires()</tt> can only be used |
| inside of a function body). This macro declares a nested class template, |
| where the template parameter is a function pointer. We then use the nested |
| class type in a typedef with the function pointer type of the constraint |
| function as the template argument. We use the <tt>type_var</tt> and |
| <tt>concept</tt> names in the nested class and typedef names to help |
| prevent name collisions.</p> |
| <pre> |
| #define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ |
| typedef void (ns::concept <type_var>::* func##type_var##concept)(); \ |
| template <func##type_var##concept _Tp1> \ |
| struct concept_checking_##type_var##concept { }; \ |
| typedef concept_checking_##type_var##concept< \ |
| BOOST_FPTR ns::concept<type_var>::constraints> \ |
| concept_checking_typedef_##type_var##concept |
| </pre> |
| |
| <p>In addition, there are versions of <tt>BOOST_CLASS_REQUIRE</tt> that |
| take more arguments, to handle concepts that include interactions between |
| two or more types. <tt>BOOST_CLASS_REQUIRE</tt> was not used in the |
| implementation of the BCCL concept checks because some compilers do not |
| implement template parameters of function pointer type. |
| <!-- We decided not to go with this version since it is easier to misuse |
| |
| To check the type parameters of class templates, we provide the |
| <tt>class_requires</tt> class which can be used inside the body of a |
| class definition (whereas <tt>function_requires()</tt> can only be |
| used inside of a function body). <tt>class_requires</tt> declares a |
| nested class template, where the template parameter is a function |
| pointer. We then use the nested class type in a typedef with the |
| function pointer type of the constraint function as the template |
| argument. |
| |
| <pre> |
| template <class Concept> |
| class class_requires |
| { |
| typedef void (Concept::* function_pointer)(); |
| |
| template <function_pointer Fptr> |
| struct dummy_struct { }; |
| public: |
| typedef dummy_struct< BOOST_FPTR Concept::constraints > check; |
| }; |
| </pre> |
| |
| <tt>class_requires</tt> was not used in the implementation of the |
| Boost Concept Checking Library concept checks because several |
| compilers do not implement template parameters of function pointer |
| type. |
| |
| --></p> |
| |
| <p><a href="./reference.htm">Next: Reference</a><br /> |
| <a href="prog_with_concepts.htm">Prev: Programming With |
| Concepts</a><br /></p> |
| <hr /> |
| |
| <table> |
| <tr valign="top"> |
| <td nowrap="nowrap">Copyright © 2000</td> |
| |
| <td><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>(<a href= |
| "mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew |
| Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>), |
| 2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>. |
| </tr> |
| </table> |
| </body> |
| </html> |