finished change, REQUIRE macro to function_requires()

[SVN r8280]
This commit is contained in:
Jeremy Siek
2000-11-21 21:39:49 +00:00
parent ddd16bb04c
commit 4759eca6b5
3 changed files with 224 additions and 203 deletions

View File

@@ -51,7 +51,8 @@ The documentation is organized into the following sections.
<LI><a href="#implementation">Implementation</a></LI> <LI><a href="#implementation">Implementation</a></LI>
<LI><a href="#reference">Reference</a></LI> <LI><a href="#reference">Reference</a></LI>
<OL> <OL>
<LI><a href="#macros">Macros</a></LI> <LI><a href="#functions">Functions</a></LI>
<LI><a href="#classes">Classes</a></LI>
<LI><a href="#basic-concepts">Basic Concept Checking Classes</a></LI> <LI><a href="#basic-concepts">Basic Concept Checking Classes</a></LI>
<LI><a href="#iterator-concepts">Iterator Concept Checking Classes</a></LI> <LI><a href="#iterator-concepts">Iterator Concept Checking Classes</a></LI>
<LI><a href="#function-object-concepts">Function Object Concept Checking Classes</a></LI> <LI><a href="#function-object-concepts">Function Object Concept Checking Classes</a></LI>
@@ -101,14 +102,6 @@ Library uses some standard C++ constructs to enforce early concept
compliance and that provides more informative error messages upon compliance and that provides more informative error messages upon
non-compliance. non-compliance.
<!--
Move this stuff to history:
We have applied this mechanism to the SGI
implementation of STL, and the changes are now in the main
distribution.
-->
<p> <p>
Note that this technique only addresses the syntactic Note that this technique only addresses the syntactic
requirements of concepts (the valid expressions and associated types). requirements of concepts (the valid expressions and associated types).
@@ -234,55 +227,76 @@ RandomAccessIterator</a>).
<h2><a name="using-concept-checks">Using Concept Checks</a></h2> <h2><a name="using-concept-checks">Using Concept Checks</a></h2>
The Boost Concept Checking Library defines several macros that make it For each concept there is a concept checking class which can be used
convenient to ensure that some type (or collection of types) models a to make sure that a given type (or set of types) models the concept.
given concept. The <tt>REQUIRE</tt> macros can be used in function The Boost Concept Checking Library includes concept checking classes
bodies and the <tt>CLASS_REQUIRES</tt> macros can be used in class for all of the concepts used in the C++ standard library and a few
bodies. The purpose of the macros is to check that the given more. The <a href="#reference">Reference</a> section below lists these
<i>type</i> models the specified <i>concept</i>. We use macros so concept checking classes. In addition, other boost libraries come with
that the checks can be conditionally removed in situations where concept checking classes for the concepts that are particular to those
faster compile time is needed. libraries. An example of one of these classes is the
<tt>EqualityComparableConcept</tt> class.
<pre> <pre>
REQUIRE(<i>type</i>, <i>concept</i>); template &lt;class T&gt; struct EqualityComparableConcept;
REQUIRE2(<i>type1</i>, <i>type2</i>, <i>concept</i>); </pre>
REQUIRE3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>concept</i>);
REQUIRE4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>);
CLASS_REQUIRES(<i>type</i>, <i>concept</i>); Each concept checking class has a member function named
CLASS_REQUIRES2(<i>type1</i>, <i>type2</i>, <i>concept</i>); <tt>constraints()</tt> which contains the valid expressions for the
CLASS_REQUIRES3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>concept</i>); concept. To check whether some type, say <tt>foo</tt>, is
CLASS_REQUIRES4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>); EqualityComparable, we need to instantiate the concept checking class
with foo: <tt>EqualityComparableConcept&lt;foo&gt;</tt> and then find
a way to get the compiler to compile the <tt>constraints()</tt>
function without actually calling it. The Boost Concept Checking
Library defines two utilities that make this easy:
<tt>function_requires()</tt> and <tt>class_requires</tt>.
<tt>function_requires()</tt> function can be used in function bodies
and the <tt>class_requires</tt> class can be used inside class
bodies. The <tt>function_requires()</tt> function takes no arguments,
but has a template parameter for the concept checking class. This
means that the instantiated concept checking class must be given as an
explicit template argument, as shown below.
<pre>
void some_function_using_foo() {
function_requires&lt; EqualityComparableConcept&lt;foo&gt; &gt;();
// ...
};
</pre>
The <tt>class_requires</tt> is a class template with a template
parameter for the concept checking class. Accessing the nested
<tt>check</tt> type within <tt>class_requires</tt> triggers the the
concept checking.
<pre>
struct some_class_using_foo {
typedef class_requires&lt; EqualityComparableConcept&lt;foo&gt; &gt;::check req1;
};
</pre> </pre>
To add concept checks to the <tt>std::stable_sort()</tt> function the To add concept checks to the <tt>std::stable_sort()</tt> function the
library implementor would simply insert <tt>REQUIRE</tt> at the top of library implementor would simply insert <tt>function_requires()</tt>
<tt>std::stable_sort()</tt> to make sure the template parameter type at the top of <tt>std::stable_sort()</tt> to make sure the template
models <a href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html"> parameter type models <a
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a>. In addition, <tt>std::stable_sort()</tt> RandomAccessIterator</a>. In addition, <tt>std::stable_sort()</tt>
requires that the <tt>value_type</tt> of the iterators be requires that the <tt>value_type</tt> of the iterators be
<a href="http://www.sgi.com/Technology/STL/LessThanComparable.html"> <a href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
LessThanComparable</a>, so we also use <tt>REQUIRE</tt> to check this. LessThanComparable</a>, so we also use <tt>function_requires()</tt> to
check this.
<pre> <pre>
template &lt;class RandomAccessIter&gt; template &lt;class RandomAccessIter&gt;
void stable_sort(RandomAccessIter first, RandomAccessIter last) void stable_sort(RandomAccessIter first, RandomAccessIter last)
{ {
REQUIRE(RandomAccessIter, RandomAccessIterator); function_requires&lt; RandomAccessIteratorConcept&lt;RandomAccessIter&gt; &gt;();
typedef typename std::iterator_traits&lt;RandomAccessIter&gt;::value_type value_type; typedef typename std::iterator_traits&lt;RandomAccessIter&gt;::value_type value_type;
REQUIRE(value_type, LessThanComparable); function_requires&lt; LessThanComparableConcept&lt;value_type&gt; &gt;();
... ...
} }
</pre> </pre>
The Boost Concept Checking library includes a concept checking class
for each of the concepts described in the SGI STL documentation. The
second argument to <tt>REQUIRE</tt> indicates which concept checking
class should be used. In the above example, the use of
<tt>LessThanComparable</tt> indicates that the
<tt>LessThanComparable_concept</tt> class will be used to check the
value type. The <a href="#reference">Reference</a> section below
lists the concept checking classes.
<!-- There are a few places where the SGI STL documentation differs <!-- There are a few places where the SGI STL documentation differs
@@ -292,8 +306,8 @@ these cases we use the definition from the C++ Standard. -->
<p> <p>
Some concepts deal with more than one type. In this case the Some concepts deal with more than one type. In this case the
corresponding concept checking class will have multiple template corresponding concept checking class will have multiple template
parameters. The following example shows how the <tt>REQUIRE2</tt> parameters. The following example shows how
macro is used with the <a <tt>function_requires()</tt> is used with the <a
href="../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a> href="../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
concept which takes two type parameters: a property map and the key concept which takes two type parameters: a property map and the key
type for the map. type for the map.
@@ -306,24 +320,25 @@ type for the map.
Buffer& Q, BFSVisitor vis, ColorMap color) Buffer& Q, BFSVisitor vis, ColorMap color)
{ {
typedef typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor Vertex; typedef typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor Vertex;
REQUIRE2(ColorMap, Vertex, ReadWritePropertyMap); function_requires&lt; ReadWritePropertyMap&lt;ColorMap, Vertex&gt; &gt;();
... ...
} }
</pre> </pre>
As an example of using the <tt>CLASS_REQUIRES</tt> macro we look at a As an example of using <tt>class_requires</tt> we look at a concept
concept check that could be added to <tt>std::vector</tt>. One check that could be added to <tt>std::vector</tt>. One requirement
requirement that is placed on the element type is that it must be <a that is placed on the element type is that it must be <a
href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</a>. href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</a>.
We can check this by inserting <tt>CLASS_REQUIRES(T, Assignable)</tt> We can check this by inserting
at the top of the definition for <tt>std::vector</tt>. <tt>class_requires&lt;AssignableConcept&lt;T&gt; &gt;</tt> at the top
of the definition for <tt>std::vector</tt>.
<pre> <pre>
namespace std { namespace std {
template &lt;class T&gt; template &lt;class T&gt;
struct vector { struct vector {
CLASS_REQUIRES(T, Assignable); typedef typename class_requires&lt; AssignableConcept&lt;T&gt; &gt;::check req;
... ...
}; };
} }
@@ -333,9 +348,10 @@ at the top of the definition for <tt>std::vector</tt>.
Although the concept checks are designed for use by generic library Although the concept checks are designed for use by generic library
implementors, they can also be useful to end users. Sometimes one may implementors, they can also be useful to end users. Sometimes one may
not be sure whether some type models a particular concept. This can not be sure whether some type models a particular concept. This can
easily be checked by creating a small program and using the easily be checked by creating a small program and using
<tt>REQUIRE</tt> macro with the type and concept in question. The <tt>function_requires()</tt> with the type and concept in question.
file <a href="./stl_concept_checks.cpp"><tt>stl_concept_checks.cpp</tt></a> The file <a
href="./stl_concept_checks.cpp"><tt>stl_concept_checks.cpp</tt></a>
gives and example of applying the concept checks to STL gives and example of applying the concept checks to STL
containers. The file is listed here: containers. The file is listed here:
@@ -356,37 +372,37 @@ containers. The file is listed here:
typedef std::deque&lt;int&gt; Deque; typedef std::deque&lt;int&gt; Deque;
typedef std::list&lt;int&gt; List; typedef std::list&lt;int&gt; List;
REQUIRE(Vector, Mutable_RandomAccessContainer); function_requires&lt; Mutable_RandomAccessContainer&lt;Vector&gt; &gt;();
REQUIRE(Vector, BackInsertionSequence); function_requires&lt; BackInsertionSequence&lt;Vector&gt; &gt;();
REQUIRE(Deque, Mutable_RandomAccessContainer); function_requires&lt; Mutable_RandomAccessContainer&lt;Deque&gt; &gt;();
REQUIRE(Deque, FrontInsertionSequence); function_requires&lt; FrontInsertionSequence&lt;Deque&gt; &gt;();
REQUIRE(Deque, BackInsertionSequence); function_requires&lt; BackInsertionSequence&lt;Deque&gt; &gt;();
REQUIRE(List, Mutable_ReversibleContainer); function_requires&lt; Mutable_ReversibleContainer&lt;List&gt; &gt;();
REQUIRE(List, FrontInsertionSequence); function_requires&lt; FrontInsertionSequence&lt;List&gt; &gt;();
REQUIRE(List, BackInsertionSequence); function_requires&lt; BackInsertionSequence&lt;List&gt; &gt;();
typedef std::set&lt;int&gt; Set; typedef std::set&lt;int&gt; Set;
typedef std::multiset&lt;int&gt; MultiSet; typedef std::multiset&lt;int&gt; MultiSet;
typedef std::map&lt;int,int&gt; Map; typedef std::map&lt;int,int&gt; Map;
typedef std::multimap&lt;int,int&gt; MultiMap; typedef std::multimap&lt;int,int&gt; MultiMap;
REQUIRE(Set, SortedAssociativeContainer); function_requires&lt; SortedAssociativeContainer&lt;Set&gt; &gt;();
REQUIRE(Set, SimpleAssociativeContainer); function_requires&lt; SimpleAssociativeContainer&lt;Set&gt; &gt;();
REQUIRE(Set, UniqueAssociativeContainer); function_requires&lt; UniqueAssociativeContainer&lt;Set&gt; &gt;();
REQUIRE(MultiSet, SortedAssociativeContainer); function_requires&lt; SortedAssociativeContainer&lt;MultiSet&gt; &gt;();
REQUIRE(MultiSet, SimpleAssociativeContainer); function_requires&lt; SimpleAssociativeContainer&lt;MultiSet&gt; &gt;();
REQUIRE(MultiSet, MultipleAssociativeContainer); function_requires&lt; MultipleAssociativeContainer&lt;MultiSet&gt; &gt;();
REQUIRE(Map, SortedAssociativeContainer); function_requires&lt; SortedAssociativeContainer&lt;Map&gt; &gt;();
REQUIRE(Map, UniqueAssociativeContainer); function_requires&lt; UniqueAssociativeContainer&lt;Map&gt; &gt;();
REQUIRE(Map, PairAssociativeContainer); function_requires&lt; PairAssociativeContainer&lt;Map&gt; &gt;();
REQUIRE(MultiMap, SortedAssociativeContainer); function_requires&lt; SortedAssociativeContainer&lt;MultiMap&gt; &gt;();
REQUIRE(MultiMap, MultipleAssociativeContainer); function_requires&lt; MultipleAssociativeContainer&lt;MultiMap&gt; &gt;();
REQUIRE(MultiMap, PairAssociativeContainer); function_requires&lt; PairAssociativeContainer&lt;MultiMap&gt; &gt;();
return 0; return 0;
} }
@@ -434,10 +450,11 @@ enforce the associated types of the concept.
struct RandomAccessIterator_concept struct RandomAccessIterator_concept
{ {
void constraints() { void constraints() {
REQUIRE(Iter, BidirectionalIterator); function_requires&lt; BidirectionalIteratorConcept&lt;Iter&gt; &gt;();
REQUIRE(Iter, LessThanComparable); function_requires&lt; LessThanComparableConcept&lt;Iter&gt; &gt;();
REQUIRE2(typename std::iterator_traits&lt;Iter&gt;::iterator_category, function_requires&lt; ConvertibleConcept&lt;
std::random_access_iterator_tag, Convertible); typename std::iterator_traits&lt;Iter&gt;::iterator_category,
std::random_access_iterator_tag&gt; &gt;();
i += n; i += n;
i = i + n; i = n + i; i = i + n; i = n + i;
@@ -739,8 +756,9 @@ We can still use the function pointer mechanism to cause instantiation
of the constraints function, however now it will be a member function of the constraints function, however now it will be a member function
pointer. To make it easy for the library implementor to invoke the pointer. To make it easy for the library implementor to invoke the
concept checks, we wrap the member function pointer mechanism in a concept checks, we wrap the member function pointer mechanism in a
macro named <tt>REQUIRE</tt>. The following code snippet shows how to function named <tt>function_requires()</tt>. The following code
use <tt>REQUIRE</tt> to make sure that the iterator is a snippet shows how to use <tt>function_requires()</tt> to make sure
that the iterator is a
<a <a
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html"> href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
RandomAccessIterator</a>. RandomAccessIterator</a>.
@@ -749,155 +767,156 @@ RandomAccessIterator</a>.
template &lt;class RandomAccessIter&gt; template &lt;class RandomAccessIter&gt;
void stable_sort(RandomAccessIter first, RandomAccessIter last) void stable_sort(RandomAccessIter first, RandomAccessIter last)
{ {
REQUIRE(RandomAccessIter, RandomAccessIterator); function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
... ...
} }
</pre> </pre>
The definition of the <tt>REQUIRE</tt> is as follows. The The definition of the <tt>function_requires()</tt> is as follows. The
<tt>type_var</tt> is the type we wish to check, and <tt>concept</tt> <tt>Concept</tt> is the concept checking class that has been
is the name that corresponds to the concept checking class. We assign instantiated with the modeling type. We assign the address of the
the address of the constraints member function to the function pointer constraints member function to the function pointer <tt>x</tt>, which
<tt>x</tt>, which causes the instantiation of the constraints function causes the instantiation of the constraints function and checking of
and checking of the concept's valid expressions. We then assign the concept's valid expressions. We then assign <tt>x</tt> to
<tt>x</tt> to <tt>x</tt> to avoid unused variable compiler warnings, <tt>x</tt> to avoid unused variable compiler warnings, and wrap
and wrap everything in a do-while loop to prevent name collisions. everything in a do-while loop to prevent name collisions.
<pre> <pre>
#define REQUIRE(type_var, concept) \ template <class Concept>
do { \ void function_requires()
void (concept##_concept &lt;type_var&gt;::*x)() = \ {
concept##_concept &lt;type_var&gt;::constraints; \ void (Concept::*x)() = BOOST_FPTR Concept::constraints;
x = x; \ ignore_unused_variable_warning(x);
} while (0) }
</pre> </pre>
To check the type parameters of class templates, we provide the To check the type parameters of class templates, we provide the
<tt>CLASS_REQUIRES</tt> macro which can be used inside the body of a <tt>class_requires</tt> class which can be used inside the body of a
class definition (whereas the <tt>REQUIRES</tt> macro can only be used class definition (whereas <tt>function_requires()</tt> can only be
inside of a function body). This macro declares a nested class used inside of a function body). <tt>class_requires</tt> declares a
template, where the template parameter is a function pointer. We then nested class template, where the template parameter is a function
use the nested class type in a typedef with the function pointer type pointer. We then use the nested class type in a typedef with the
of the constraint function as the template argument. We use the function pointer type of the constraint function as the template
<tt>type_var</tt> and <tt>concept</tt> names in the nested class and argument.
typedef names to help prevent name collisions.
<pre> <pre>
#define CLASS_REQUIRES(type_var, concept) \ template &lt;class Concept&gt;
typedef void (concept##_concept &lt;type_var&gt; \ class class_requires
::* func##type_var##concept)(); \ {
\ typedef void (Concept::* function_pointer)();
template &lt;func##type_var##concept FuncPtr&gt; \
struct dummy_struct_##type_var##concept { }; \ template &lt;function_pointer Fptr&gt;
\ struct dummy_struct { };
typedef dummy_struct_##type_var##concept&lt; \ public:
concept##_concept &lt;type_var&gt;::constraints&gt; \ typedef dummy_struct&lt; BOOST_FPTR Concept::constraints &gt; check;
dummy_typedef_##type_var##concept };
</pre> </pre>
In addition, there are versions of <tt>REQUIRE</tt> and <tt>class_requires</tt> was not used in the implementation of the
<tt>CLASS_REQUIRES</tt> that take more arguments, to handle concepts Boost Concept Checking Library concept checks because several
that include interactions between two or more types. compilers do not implement template parameters of function pointer
<tt>CLASS_REQUIRES</tt> was not used in the implementation of the STL type.
concept checks because several compilers do not implement template
parameters of function pointer type.
<h2><a name="reference">Reference</a></h2> <h2><a name="reference">Reference</a></h2>
<h3><a name="macros">Macros</a></h3> <h3><a name="functions">Functions</a></h3>
<pre> <pre>
// Apply concept checks in function definitions. template &lt;class Concept&gt;
REQUIRE(<i>type</i>, <i>concept</i>); void function_requires();
REQUIRE2(<i>type1</i>, <i>type2</i>, <i>concept</i>); </pre>
REQUIRE3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>concept</i>);
REQUIRE4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>); <h3><a name="classes">Classes</a></h3>
<pre>
template &lt;class Concept&gt;
struct class_requires {
typedef ... check;
};
</pre> </pre>
<pre> <pre>
// Apply concept checks in class definitions. // Make sure that <i>Type1</i> and <i>Type2</i> are exactly the same type.
CLASS_REQUIRES(<i>type</i>, <i>concept</i>); // If they are not, then the nested typedef for <tt>type</tt> will
CLASS_REQUIRES2(<i>type1</i>, <i>type2</i>, <i>concept</i>); // not exist and cause a compiler error.
CLASS_REQUIRES3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>concept</i>); template &lt;class Type1, class Type2&gt;
CLASS_REQUIRES4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>); struct require_same {
</pre> typedef ... type;
};
<pre> // usage example
// Make sure that <i>type1</i> and <i>type2</i> are exactly the same type typedef typedef require_same<int,int>::type req1; // this will compile OK
REQUIRE_SAME_TYPE(<i>type1</i>, <i>type2</i>); typedef typedef require_same<int,float>::type req1; // this will cause a compiler error
</pre> </pre>
<h3><a name="basic-concepts">Basic Concept Checking Classes</a></h3> <h3><a name="basic-concepts">Basic Concept Checking Classes</a></h3>
<pre> <pre>
template &lt;class T&gt; struct Integer_concept; // Is T a built-in integer type? template &lt;class T&gt; struct Integer_concept; // Is T a built-in integer type?
template &lt;class T&gt; struct SignedInteger_concept; // Is T a built-in signed integer type? template &lt;class T&gt; struct SignedIntegerConcept; // Is T a built-in signed integer type?
template &lt;class X, class Y&gt; struct Convertible_concept; // Is X convertible to Y? template &lt;class X, class Y&gt; struct ConvertibleConcept; // Is X convertible to Y?
template &lt;class T&gt; struct Assignable_concept; template &lt;class T&gt; struct AssignableConcept;
template &lt;class T&gt; struct DefaultConstructible_concept; template &lt;class T&gt; struct DefaultConstructibleConcept;
template &lt;class T&gt; struct CopyConstructible_concept; template &lt;class T&gt; struct CopyConstructibleConcept;
template &lt;class T&gt; struct Boolean_concept; template &lt;class T&gt; struct BooleanConcept;
template &lt;class T&gt; struct EqualityComparable_concept; template &lt;class T&gt; struct EqualityComparableConcept;
// Is class T equality comparable on the left side with type Left? // Is class T equality comparable on the left side with type Left?
template &lt;class T, class Left&gt; struct LeftEqualityComparable_concept; template &lt;class T, class Left&gt; struct LeftEqualityComparableConcept;
template &lt;class T&gt; struct LessThanComparable_concept; template &lt;class T&gt; struct LessThanComparableConcept;
</pre> </pre>
<h3><a name="iterator-concepts">Iterator Concept Checking Classes</a></h3> <h3><a name="iterator-concepts">Iterator Concept Checking Classes</a></h3>
<pre> <pre>
template &lt;class Iter&gt; struct TrivialIterator_concept; template &lt;class Iter&gt; struct TrivialIteratorConcept;
template &lt;class Iter&gt; struct Mutable_TrivialIterator_concept; template &lt;class Iter&gt; struct Mutable_TrivialIteratorConcept;
template &lt;class Iter&gt; struct InputIterator_concept; template &lt;class Iter&gt; struct InputIteratorConcept;
template &lt;class Iter, class T&gt; struct OutputIterator_concept; template &lt;class Iter, class T&gt; struct OutputIteratorConcept;
template &lt;class Iter&gt; struct ForwardIterator_concept; template &lt;class Iter&gt; struct ForwardIteratorConcept;
template &lt;class Iter&gt; struct Mutable_ForwardIterator_concept; template &lt;class Iter&gt; struct Mutable_ForwardIteratorConcept;
template &lt;class Iter&gt; struct BidirectionalIterator_concept; template &lt;class Iter&gt; struct BidirectionalIteratorConcept;
template &lt;class Iter&gt; struct Mutable_BidirectionalIterator_concept; template &lt;class Iter&gt; struct Mutable_BidirectionalIteratorConcept;
template &lt;class Iter&gt; struct RandomAccessIterator_concept; template &lt;class Iter&gt; struct RandomAccessIteratorConcept;
template &lt;class Iter&gt; struct Mutable_RandomAccessIterator_concept; template &lt;class Iter&gt; struct Mutable_RandomAccessIteratorConcept;
</pre> </pre>
<h3><a name="function-object-concepts">Function Object Concept Checking Classes</a></h3> <h3><a name="function-object-concepts">Function Object Concept Checking Classes</a></h3>
<pre> <pre>
template &lt;class Func, class Return&gt; struct Generator_concept; template &lt;class Func, class Return&gt; struct GeneratorConcept;
template &lt;class Func, class Return, class Arg&gt; struct UnaryFunction_concept; template &lt;class Func, class Return, class Arg&gt; struct UnaryFunctionConcept;
template &lt;class Func, class Return, class First, class Second&gt; struct BinaryFunction_concept; template &lt;class Func, class Return, class First, class Second&gt; struct BinaryFunctionConcept;
template &lt;class Func, class Arg&gt; struct UnaryPredicate_concept; template &lt;class Func, class Arg&gt; struct UnaryPredicateConcept;
template &lt;class Func, class First, class Second&gt; struct BinaryPredicate_concept; template &lt;class Func, class First, class Second&gt; struct BinaryPredicateConcept;
template &lt;class Func, class First, class Second&gt; struct Const_BinaryPredicate_concept {; template &lt;class Func, class First, class Second&gt; struct Const_BinaryPredicateConcept {;
</pre> </pre>
<h3><a name="container-concepts">Container Concept Checking Classes</a></h3> <h3><a name="container-concepts">Container Concept Checking Classes</a></h3>
<pre> <pre>
template &lt;class C&gt; struct Container_concept; template &lt;class C&gt; struct ContainerConcept;
template &lt;class C&gt; struct Mutable_Container_concept; template &lt;class C&gt; struct Mutable_ContainerConcept;
template &lt;class C&gt; struct ForwardContainer_concept; template &lt;class C&gt; struct ForwardContainerConcept;
template &lt;class C&gt; struct Mutable_ForwardContainer_concept; template &lt;class C&gt; struct Mutable_ForwardContainerConcept;
template &lt;class C&gt; struct ReversibleContainer_concept; template &lt;class C&gt; struct ReversibleContainerConcept;
template &lt;class C&gt; struct Mutable_ReversibleContainer_concept; template &lt;class C&gt; struct Mutable_ReversibleContainerConcept;
template &lt;class C&gt; struct RandomAccessContainer_concept; template &lt;class C&gt; struct RandomAccessContainerConcept;
template &lt;class C&gt; struct Mutable_RandomAccessContainer_concept; template &lt;class C&gt; struct Mutable_RandomAccessContainerConcept;
template &lt;class C&gt; struct Sequence_concept; template &lt;class C&gt; struct SequenceConcept;
template &lt;class C&gt; struct FrontInsertionSequence_concept; template &lt;class C&gt; struct FrontInsertionSequenceConcept;
template &lt;class C&gt; struct BackInsertionSequence_concept; template &lt;class C&gt; struct BackInsertionSequenceConcept;
template &lt;class C&gt; struct AssociativeContainer_concept; template &lt;class C&gt; struct AssociativeContainerConcept;
template &lt;class C&gt; struct UniqueAssociativeContainer_concept; template &lt;class C&gt; struct UniqueAssociativeContainerConcept;
template &lt;class C&gt; struct MultipleAssociativeContainer_concept; template &lt;class C&gt; struct MultipleAssociativeContainerConcept;
template &lt;class C&gt; struct SimpleAssociativeContainer_concept; template &lt;class C&gt; struct SimpleAssociativeContainerConcept;
template &lt;class C&gt; struct PairAssociativeContainer_concept; template &lt;class C&gt; struct PairAssociativeContainerConcept;
template &lt;class C&gt; struct SortedAssociativeContainer_concept; template &lt;class C&gt; struct SortedAssociativeContainerConcept;
</pre> </pre>

View File

@@ -25,11 +25,13 @@
#include <slist> #include <slist>
#endif #endif
//#define BOOST_HIDE_EXPECTED_ERRORS #define BOOST_HIDE_EXPECTED_ERRORS
int int
main() main()
{ {
using namespace boost;
#if defined(_ITERATOR_) && defined(BOOST_HIDE_EXPECTED_ERRORS) #if defined(_ITERATOR_) && defined(BOOST_HIDE_EXPECTED_ERRORS)
// VC++ STL implementation is not standard conformant and // VC++ STL implementation is not standard conformant and
// fails to pass these concept checks // fails to pass these concept checks
@@ -39,27 +41,27 @@ main()
typedef std::list<int> List; typedef std::list<int> List;
// VC++ missing pointer and const_pointer typedefs // VC++ missing pointer and const_pointer typedefs
BOOST_FUNCTION_REQUIRES(Vector, Mutable_RandomAccessContainerConcept); function_requires< Mutable_RandomAccessContainerConcept<Vector> >();
BOOST_FUNCTION_REQUIRES(Vector, BackInsertionSequenceConcept); function_requires< BackInsertionSequenceConcept<Vector> >();
#if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS)) #if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS))
#if !(defined(__sgi) && defined(BOOST_HIDE_EXPECTED_ERRORS)) #if !(defined(__sgi) && defined(BOOST_HIDE_EXPECTED_ERRORS))
// old deque iterator missing n + iter operation // old deque iterator missing n + iter operation
BOOST_FUNCTION_REQUIRES(Deque, Mutable_RandomAccessContainerConcept); function_requires< Mutable_RandomAccessContainerConcept<Deque> >();
#endif #endif
// warnings about signed and unsigned in old deque version // warnings about signed and unsigned in old deque version
BOOST_FUNCTION_REQUIRES(Deque, FrontInsertionSequenceConcept); function_requires< FrontInsertionSequenceConcept<Deque> >();
BOOST_FUNCTION_REQUIRES(Deque, BackInsertionSequenceConcept); function_requires< BackInsertionSequenceConcept<Deque> >();
#endif #endif
// VC++ missing pointer and const_pointer typedefs // VC++ missing pointer and const_pointer typedefs
BOOST_FUNCTION_REQUIRES(List, Mutable_ReversibleContainerConcept); function_requires< Mutable_ReversibleContainerConcept<List> >();
BOOST_FUNCTION_REQUIRES(List, FrontInsertionSequenceConcept); function_requires< FrontInsertionSequenceConcept<List> >();
BOOST_FUNCTION_REQUIRES(List, BackInsertionSequenceConcept); function_requires< BackInsertionSequenceConcept<List> >();
#ifndef BOOST_NO_SLIST #ifndef BOOST_NO_SLIST
typedef std::slist<int> SList; typedef std::slist<int> SList;
BOOST_FUNCTION_REQUIRES(SList, FrontInsertionSequenceConcept); function_requires< FrontInsertionSequenceConcept<SList> >();
#endif #endif
typedef std::set<int> Set; typedef std::set<int> Set;
@@ -67,21 +69,21 @@ main()
typedef std::map<int,int> Map; typedef std::map<int,int> Map;
typedef std::multimap<int,int> MultiMap; typedef std::multimap<int,int> MultiMap;
BOOST_FUNCTION_REQUIRES(Set, SortedAssociativeContainerConcept); function_requires< SortedAssociativeContainerConcept<Set> >();
BOOST_FUNCTION_REQUIRES(Set, SimpleAssociativeContainerConcept); function_requires< SimpleAssociativeContainerConcept<Set> >();
BOOST_FUNCTION_REQUIRES(Set, UniqueAssociativeContainerConcept); function_requires< UniqueAssociativeContainerConcept<Set> >();
BOOST_FUNCTION_REQUIRES(MultiSet, SortedAssociativeContainerConcept); function_requires< SortedAssociativeContainerConcept<MultiSet> >();
BOOST_FUNCTION_REQUIRES(MultiSet, SimpleAssociativeContainerConcept); function_requires< SimpleAssociativeContainerConcept<MultiSet> >();
BOOST_FUNCTION_REQUIRES(MultiSet, MultipleAssociativeContainerConcept); function_requires< MultipleAssociativeContainerConcept<MultiSet> >();
BOOST_FUNCTION_REQUIRES(Map, SortedAssociativeContainerConcept); function_requires< SortedAssociativeContainerConcept<Map> >();
BOOST_FUNCTION_REQUIRES(Map, UniqueAssociativeContainerConcept); function_requires< UniqueAssociativeContainerConcept<Map> >();
BOOST_FUNCTION_REQUIRES(Map, PairAssociativeContainerConcept); function_requires< PairAssociativeContainerConcept<Map> >();
BOOST_FUNCTION_REQUIRES(MultiMap, SortedAssociativeContainerConcept); function_requires< SortedAssociativeContainerConcept<MultiMap> >();
BOOST_FUNCTION_REQUIRES(MultiMap, MultipleAssociativeContainerConcept); function_requires< MultipleAssociativeContainerConcept<MultiMap> >();
BOOST_FUNCTION_REQUIRES(MultiMap, PairAssociativeContainerConcept); function_requires< PairAssociativeContainerConcept<MultiMap> >();
#endif #endif
return 0; return 0;

View File

@@ -30,17 +30,17 @@ main()
} }
{ {
/* /*
SGI STL Docs and the C++ standard (25.1.2) BOOST_FUNCTION_REQUIRESments for SGI STL Docs and the C++ standard (25.1.2) requirements for
std::for_each() are broken. They should be specified as follows: std::for_each() are broken. They should be specified as follows:
template <class InputIterator, class LeftEqualityComparable> template <class InputIterator, class T>
InputIterator find(InputIterator first, InputIterator last, InputIterator find(InputIterator first, InputIterator last,
const LeftEqualityComparable& value) const T& value)
{ {
BOOST_FUNCTION_REQUIRES(InputIterator, InputIterator); function_requires< InputIteratorConcept<InputIterator> >();
typedef typename std::iterator_traits<InputIterator>::value_type typedef typename std::iterator_traits<InputIterator>::value_type
value_type; value_type;
BOOST_FUNCTION_REQUIRES(LeftEqualityComparable, value_type, LeftEqualityComparable); function_requires< EqualityComparable2<value_type, T> >();
... ...
} }
*/ */
@@ -74,7 +74,7 @@ main()
{ {
typedef input_iterator_archetype<null_archetype> InIter; typedef input_iterator_archetype<null_archetype> InIter;
InIter in; InIter in;
BOOST_FUNCTION_REQUIRES(InIter, InputIteratorConcept); function_requires< InputIteratorConcept<InIter> >();
left_equality_comparable_archetype<null_archetype> value(dummy_cons); left_equality_comparable_archetype<null_archetype> value(dummy_cons);
std::iterator_traits<InIter>::difference_type std::iterator_traits<InIter>::difference_type
n = std::count(in, in, value); n = std::count(in, in, value);