forked from boostorg/concept_check
changing directory name, and reorganizing docs
[SVN r8410]
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
<h2><a name="using-concept-checks">Using Concept Checks</a></h2>
|
||||
|
||||
For each concept there is a concept checking class which can be used
|
||||
to make sure that a given type (or set of types) models the concept.
|
||||
The Boost Concept Checking Library includes concept checking classes
|
||||
for all of the concepts used in the C++ standard library and a few
|
||||
more. The <a href="#reference">Reference</a> section below lists these
|
||||
concept checking classes. In addition, other boost libraries come with
|
||||
concept checking classes for the concepts that are particular to those
|
||||
libraries. An example of one of these classes is the
|
||||
<tt>EqualityComparableConcept</tt> class.
|
||||
|
||||
<pre>
|
||||
template <class T> struct EqualityComparableConcept;
|
||||
</pre>
|
||||
|
||||
Each concept checking class has a member function named
|
||||
<tt>constraints()</tt> which contains the valid expressions for the
|
||||
concept. To check whether some type, say <tt>foo</tt>, is
|
||||
EqualityComparable, we need to instantiate the concept checking class
|
||||
with foo: <tt>EqualityComparableConcept<foo></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>BOOST_CLASS_REQUIRES</tt>.
|
||||
<tt>function_requires()</tt> function can be used in function bodies
|
||||
and the <tt>BOOST_CLASS_REQUIRES</tt> macro 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< EqualityComparableConcept<foo> >();
|
||||
// ...
|
||||
};
|
||||
</pre>
|
||||
|
||||
The <tt>BOOST_CLASS_REQUIRES</tt> macro can be used inside a class
|
||||
definition to check whether some type models a concept.
|
||||
|
||||
<pre>
|
||||
struct some_class_using_foo {
|
||||
BOOST_CLASS_REQUIRES(foo, EqualityComparableConcept);
|
||||
};
|
||||
</pre>
|
||||
|
||||
To add concept checks to the <tt>std::stable_sort()</tt> function the
|
||||
library implementor would simply insert <tt>function_requires()</tt>
|
||||
at the top of <tt>std::stable_sort()</tt> to make sure the template
|
||||
parameter type models <a
|
||||
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>. In addition, <tt>std::stable_sort()</tt>
|
||||
requires that the <tt>value_type</tt> of the iterators be
|
||||
<a href="http://www.sgi.com/Technology/STL/LessThanComparable.html">
|
||||
LessThanComparable</a>, so we also use <tt>function_requires()</tt> to
|
||||
check this.
|
||||
|
||||
<pre>
|
||||
template <class RandomAccessIter>
|
||||
void stable_sort(RandomAccessIter first, RandomAccessIter last)
|
||||
{
|
||||
function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
|
||||
typedef typename std::iterator_traits<RandomAccessIter>::value_type value_type;
|
||||
function_requires< LessThanComparableConcept<value_type> >();
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
<!-- There are a few places where the SGI STL documentation differs
|
||||
from the corresponding requirements described in the C++ Standard. In
|
||||
these cases we use the definition from the C++ Standard. -->
|
||||
|
||||
<p>
|
||||
Some concepts deal with more than one type. In this case the
|
||||
corresponding concept checking class will have multiple template
|
||||
parameters. The following example shows how
|
||||
<tt>function_requires()</tt> is used with the <a
|
||||
href="../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
|
||||
concept which takes two type parameters: a property map and the key
|
||||
type for the map.
|
||||
|
||||
<pre>
|
||||
template <class IncidenceGraph, class Buffer, class BFSVisitor,
|
||||
class ColorMap>
|
||||
void breadth_first_search(IncidenceGraph& g,
|
||||
typename graph_traits<IncidenceGraph>::vertex_descriptor s,
|
||||
Buffer& Q, BFSVisitor vis, ColorMap color)
|
||||
{
|
||||
typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
|
||||
function_requires< ReadWritePropertyMap<ColorMap, Vertex> >();
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
As an example of using <tt>class_requires</tt> we look at a concept
|
||||
check that could be added to <tt>std::vector</tt>. One requirement
|
||||
that is placed on the element type is that it must be <a
|
||||
href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</a>.
|
||||
We can check this by inserting
|
||||
<tt>class_requires<AssignableConcept<T> ></tt> at the top
|
||||
of the definition for <tt>std::vector</tt>.
|
||||
|
||||
<pre>
|
||||
namespace std {
|
||||
template <class T>
|
||||
struct vector {
|
||||
typedef typename class_requires< AssignableConcept<T> >::check req;
|
||||
...
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
Although the concept checks are designed for use by generic library
|
||||
implementors, they can also be useful to end users. Sometimes one may
|
||||
not be sure whether some type models a particular concept. This can
|
||||
easily be checked by creating a small program and using
|
||||
<tt>function_requires()</tt> with the type and concept in question.
|
||||
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
|
||||
containers. The file is listed here:
|
||||
|
||||
<pre>
|
||||
#include <boost/concept_checks.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
typedef std::vector<int> Vector;
|
||||
typedef std::deque<int> Deque;
|
||||
typedef std::list<int> List;
|
||||
|
||||
function_requires< Mutable_RandomAccessContainer<Vector> >();
|
||||
function_requires< BackInsertionSequence<Vector> >();
|
||||
|
||||
function_requires< Mutable_RandomAccessContainer<Deque> >();
|
||||
function_requires< FrontInsertionSequence<Deque> >();
|
||||
function_requires< BackInsertionSequence<Deque> >();
|
||||
|
||||
function_requires< Mutable_ReversibleContainer<List> >();
|
||||
function_requires< FrontInsertionSequence<List> >();
|
||||
function_requires< BackInsertionSequence<List> >();
|
||||
|
||||
typedef std::set<int> Set;
|
||||
typedef std::multiset<int> MultiSet;
|
||||
typedef std::map<int,int> Map;
|
||||
typedef std::multimap<int,int> MultiMap;
|
||||
|
||||
function_requires< SortedAssociativeContainer<Set> >();
|
||||
function_requires< SimpleAssociativeContainer<Set> >();
|
||||
function_requires< UniqueAssociativeContainer<Set> >();
|
||||
|
||||
function_requires< SortedAssociativeContainer<MultiSet> >();
|
||||
function_requires< SimpleAssociativeContainer<MultiSet> >();
|
||||
function_requires< MultipleAssociativeContainer<MultiSet> >();
|
||||
|
||||
function_requires< SortedAssociativeContainer<Map> >();
|
||||
function_requires< UniqueAssociativeContainer<Map> >();
|
||||
function_requires< PairAssociativeContainer<Map> >();
|
||||
|
||||
function_requires< SortedAssociativeContainer<MultiMap> >();
|
||||
function_requires< MultipleAssociativeContainer<MultiMap> >();
|
||||
function_requires< PairAssociativeContainer<MultiMap> >();
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
||||
Reference in New Issue
Block a user