forked from boostorg/concept_check
new file
[SVN r7737]
This commit is contained in:
166
concept_checking.html
Normal file
166
concept_checking.html
Normal file
@@ -0,0 +1,166 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 2000
|
||||
--
|
||||
-- Permission to use, copy, modify, distribute and sell this software
|
||||
-- and its documentation for any purpose is hereby granted without fee,
|
||||
-- provided that the above copyright notice appears in all copies and
|
||||
-- that both that copyright notice and this permission notice appear
|
||||
-- in supporting documentation. We make no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Concept Checking</Title>
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<IMG SRC="../../c++boost.gif"
|
||||
ALT="C++ Boost">
|
||||
|
||||
<BR Clear>
|
||||
|
||||
<H2><A NAME="SECTION00744000000000000000"></A>
|
||||
<A NAME="sec:concept-checking"></A>
|
||||
<BR>
|
||||
Concept Checking
|
||||
</H2>
|
||||
|
||||
<p>
|
||||
header <a href="../../boost/pending/concept_checks.hpp"><tt>boost/concept_checks.hpp</tt></a>
|
||||
|
||||
<P>
|
||||
The C++ language does not provide direct support for ensuring that
|
||||
template arguments meet the requirements demanded of them by the
|
||||
generic algorithm or template class. This means that if the user makes
|
||||
an error, the resulting compiler error will point to somewhere deep
|
||||
inside the implementation of the generic algorithm, giving an error
|
||||
that may not be easy to match with the cause.
|
||||
|
||||
<P>
|
||||
We have developed a method for forcing the compiler to give better
|
||||
error messages. The idea is to exercise all the requirements placed on
|
||||
the template arguments at the very beginning of the generic algorithm.
|
||||
We have created some macros and a methodology for how to do this.
|
||||
|
||||
<P>
|
||||
Suppose we wish to add concept checks to the STL <a
|
||||
href="http://www.sgi.com/Technology/STL/copy.html"><TT>copy()</TT></a>
|
||||
algorithm, which has the following prototype.
|
||||
<PRE>
|
||||
template <class InIter, class OutIter>
|
||||
OutIter copy(InIter first, InIter last, OutIter result);
|
||||
</PRE>
|
||||
We will need to make sure the <TT>InIter</TT> is a model of <a
|
||||
href="http://www.sgi.com/Technology/STL/InputIterator.html">InputIterator</a>
|
||||
and that <TT>OutIter</TT> is a model of <a
|
||||
href="http://www.sgi.com/Technology/STL/OutputIterator.html">OutputIterator</a>. The
|
||||
first step is to create the code that will exercise the expressions
|
||||
associated with each of these concepts. The following is the concept
|
||||
checking class for <a
|
||||
href="http://www.sgi.com/Technology/STL/OutputIterator.html">OutputIterator</a>.
|
||||
The iterator objects <TT>i</TT> and <TT>j</TT> are data members of the
|
||||
concept checking class which would normally require the <TT>Iter</TT>
|
||||
type to be <a
|
||||
href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</a>. However,
|
||||
we never create instances of concept checking classes so this
|
||||
requirement is not induced.
|
||||
|
||||
<P>
|
||||
<PRE>
|
||||
template <class Iter>
|
||||
struct OutputIterator {
|
||||
CLASS_REQUIRES(Iter, Assignable);
|
||||
void constraints() {
|
||||
(void)*i; // require dereference operator
|
||||
++i; // require preincrement operator
|
||||
i++; // require postincrement operator
|
||||
*i++ = *j; // require postincrement and assignment
|
||||
}
|
||||
Iter i, j;
|
||||
};
|
||||
</PRE>
|
||||
|
||||
<P>
|
||||
Once the concept checking classes are complete, one simply needs to
|
||||
invoke them at the beginning of the generic algorithm using our
|
||||
<TT>REQUIRE</TT> macro. Here's what the STL <TT>copy()</TT> algorithm
|
||||
looks like with the concept checks inserted.
|
||||
|
||||
<P>
|
||||
<PRE>
|
||||
template <class InIter, class OutIter>
|
||||
OutIter copy(InIter first, InIter last, OutIter result)
|
||||
{
|
||||
REQUIRE(OutIter, OutputIterator);
|
||||
REQUIRE(InIter, InputIterator);
|
||||
return copy_aux(first, last, result, VALUE_TYPE(first));
|
||||
}
|
||||
</PRE>
|
||||
|
||||
<P>
|
||||
Looking back at the <TT>OutputIterator</TT> concept checking class, you
|
||||
might wonder why we used the <TT>CLASS_REQUIRES</TT> macro instead of
|
||||
just <TT>REQUIRE</TT>. The reason for this is that different tricks are
|
||||
needed to force compilation of the checking code when invoking the
|
||||
macro from inside a class definition instead of a function.
|
||||
|
||||
<P>
|
||||
For the most part, the user does not need to know how to create
|
||||
concept checks and insert them in generic algorithms, however it is
|
||||
good to know what they are. This will make the error messages coming
|
||||
from libraries that use concept checks easier to understand. Also if
|
||||
you are unsure about whether you can use a certain class with a
|
||||
particular algorithm, or whether some custom-made class of your own is
|
||||
compatible, a good first check is to invoke the appropriate concept
|
||||
checker.
|
||||
|
||||
<P>
|
||||
Here's a quick example program that one could write to see if the
|
||||
types <a
|
||||
href="../graph/adjacency_list.html"><TT>adjacency_list</TT></a> and <a
|
||||
href="../graph/edge_list.html"><TT>edge_list</TT></a> really model the
|
||||
concepts they claim to.
|
||||
|
||||
<P>
|
||||
<PRE>
|
||||
#include <boost/graph/graph_concepts.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/graph/edge_list.hpp>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
int main(int,char*[])
|
||||
{
|
||||
typedef adjacency_list<listS,vecS,bidirectionalS> AdjList;
|
||||
REQUIRE(AdjList, VertexAndEdgeListGraph);
|
||||
REQUIRE(AdjList, BidirectionalGraph);
|
||||
|
||||
typedef std::pair<int, int> E;
|
||||
typedef edge_list<E*, E, int> EdgeList;
|
||||
REQUIRE(EdgeList, EdgeListGraph);
|
||||
|
||||
return 0;
|
||||
}
|
||||
</PRE>
|
||||
|
||||
<P>
|
||||
If you create your own generic algorithms we highly encourage you to use
|
||||
and publish the corresponding concept checks.
|
||||
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>,
|
||||
Univ.of Notre Dame (<A
|
||||
HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)<br>
|
||||
<A HREF=http://www.lsc.nd.edu/~llee1>Lie-Quan Lee</A>, Univ.of Notre Dame (<A HREF="mailto:llee1@lsc.nd.edu">llee1@lsc.nd.edu</A>)<br>
|
||||
<A HREF=http://www.lsc.nd.edu/~lums>Andrew Lumsdaine</A>,
|
||||
Univ.of Notre Dame (<A
|
||||
HREF="mailto:lums@lsc.nd.edu">lums@lsc.nd.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
Reference in New Issue
Block a user