mirror of
https://github.com/boostorg/concept_check.git
synced 2026-01-26 16:52:19 +01:00
182 lines
7.0 KiB
HTML
182 lines
7.0 KiB
HTML
<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_check.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>
|
|
|