| 1 | <HTML> | 
|---|
| 2 | <!-- | 
|---|
| 3 |   -- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000 | 
|---|
| 4 |   -- | 
|---|
| 5 |   -- Permission to use, copy, modify, distribute and sell this software | 
|---|
| 6 |   -- and its documentation for any purpose is hereby granted without fee, | 
|---|
| 7 |   -- provided that the above copyright notice appears in all copies and | 
|---|
| 8 |   -- that both that copyright notice and this permission notice appear | 
|---|
| 9 |   -- in supporting documentation.  We make no | 
|---|
| 10 |   -- representations about the suitability of this software for any | 
|---|
| 11 |   -- purpose.  It is provided "as is" without express or implied warranty. | 
|---|
| 12 |   --> | 
|---|
| 13 | <Head> | 
|---|
| 14 | <Title>Creating Concept Checking Classes</Title> | 
|---|
| 15 | <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"  | 
|---|
| 16 |         ALINK="#ff0000">  | 
|---|
| 17 | <IMG SRC="../../boost.png"  | 
|---|
| 18 |      ALT="C++ Boost" width="277" height="86">  | 
|---|
| 19 |  | 
|---|
| 20 | <BR Clear> | 
|---|
| 21 |  | 
|---|
| 22 |  | 
|---|
| 23 | <h2><a name="creating-concept-checks">Creating Concept Checking Classes</a></h2> | 
|---|
| 24 |  | 
|---|
| 25 | As an example of how to create a concept checking class, we look | 
|---|
| 26 | at how to create the corresponding checks for the | 
|---|
| 27 | <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> | 
|---|
| 28 | RandomAccessIterator</a> concept. First, as a convention we name the | 
|---|
| 29 | concept checking class after the concept, and add the suffix | 
|---|
| 30 | ``<tt>Concept</tt>''. Next we must define a member function named | 
|---|
| 31 | <tt>constraints()</tt> in which we will exercise the valid expressions | 
|---|
| 32 | of the concept. <tt>function_requires()</tt> expects this function's | 
|---|
| 33 | signature to appear exactly as it is appears below: a <tt>void</tt> | 
|---|
| 34 | non-const member function with no parameters. | 
|---|
| 35 |  | 
|---|
| 36 | <p> | 
|---|
| 37 | The first part of the <tt>constraints()</tt> function includes | 
|---|
| 38 | the requirements that correspond to the <i>refinement</i> relationship | 
|---|
| 39 | between <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> | 
|---|
| 40 | RandomAccessIterator</a> and the concepts which it builds upon: | 
|---|
| 41 | <a href="http://www.sgi.com/tech/stl/BidirectionalIterator.html"> | 
|---|
| 42 | BidirectionalIterator</a> and | 
|---|
| 43 | <a href="http://www.sgi.com/tech/stl/LessThanComparable.html"> | 
|---|
| 44 | LessThanComparable</a>. We could have instead used | 
|---|
| 45 | <tt>BOOST_CLASS_REQUIRE</tt> and placed these requirements in the class | 
|---|
| 46 | body, however <tt>BOOST_CLASS_REQUIRE</tt> uses C++ language features that | 
|---|
| 47 | are less portable. | 
|---|
| 48 |  | 
|---|
| 49 | <p> | 
|---|
| 50 | Next we check that the <tt>iterator_category</tt> of the iterator is | 
|---|
| 51 | either <tt>std::random_access_iterator_tag</tt> or a derived class. | 
|---|
| 52 | After that we write out some code that corresponds to the valid | 
|---|
| 53 | expressions of the <a | 
|---|
| 54 | href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> | 
|---|
| 55 | RandomAccessIterator</a> concept. Typedefs can also be added to | 
|---|
| 56 | enforce the associated types of the concept. | 
|---|
| 57 |  | 
|---|
| 58 | <pre> | 
|---|
| 59 |   template <class Iter> | 
|---|
| 60 |   struct RandomAccessIterator_concept | 
|---|
| 61 |   { | 
|---|
| 62 |     void constraints() { | 
|---|
| 63 |       function_requires< BidirectionalIteratorConcept<Iter> >(); | 
|---|
| 64 |       function_requires< LessThanComparableConcept<Iter> >(); | 
|---|
| 65 |       function_requires< ConvertibleConcept< | 
|---|
| 66 |         typename std::iterator_traits<Iter>::iterator_category, | 
|---|
| 67 |         std::random_access_iterator_tag> >(); | 
|---|
| 68 |  | 
|---|
| 69 |       i += n; | 
|---|
| 70 |       i = i + n; i = n + i; | 
|---|
| 71 |       i -= n; | 
|---|
| 72 |       i = i - n; | 
|---|
| 73 |       n = i - j; | 
|---|
| 74 |       i[n]; | 
|---|
| 75 |     } | 
|---|
| 76 |     Iter i, j; | 
|---|
| 77 |     typename std::iterator_traits<Iter>::difference_type n; | 
|---|
| 78 |   }; | 
|---|
| 79 | } | 
|---|
| 80 | </pre> | 
|---|
| 81 |  | 
|---|
| 82 | One potential pitfall in designing concept checking classes is using | 
|---|
| 83 | more expressions in the constraint function than necessary. For | 
|---|
| 84 | example, it is easy to accidentally use the default constructor to | 
|---|
| 85 | create the objects that will be needed in the expressions (and not all | 
|---|
| 86 | concepts require a default constructor). This is the reason we write | 
|---|
| 87 | the constraint function as a member function of a class. The objects | 
|---|
| 88 | involved in the expressions are declared as data members of the class. | 
|---|
| 89 | Since objects of the constraints class template are never | 
|---|
| 90 | instantiated, the default constructor for the concept checking class | 
|---|
| 91 | is never instantiated. Hence the data member's default constructors | 
|---|
| 92 | are never instantiated (C++ Standard Section 14.7.1 9). | 
|---|
| 93 |  | 
|---|
| 94 | <p> | 
|---|
| 95 | <a href="./concept_covering.htm">Next: Concept Covering and Archetypes</a><br> | 
|---|
| 96 | <a href="./using_concept_check.htm">Prev: Using Concept Checks</a> | 
|---|
| 97 |  | 
|---|
| 98 |  | 
|---|
| 99 | <br> | 
|---|
| 100 | <HR> | 
|---|
| 101 | <TABLE> | 
|---|
| 102 | <TR valign=top> | 
|---|
| 103 | <TD nowrap>Copyright © 2000</TD><TD> | 
|---|
| 104 | <A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A | 
|---|
| 105 | HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>) | 
|---|
| 106 | Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>) | 
|---|
| 107 | </TD></TR></TABLE> | 
|---|
| 108 |  | 
|---|
| 109 | </BODY> | 
|---|
| 110 | </HTML>  | 
|---|