Updated Concept Check library documentation.

Changed BOOST_CONCEPT_WHERE to BOOST_CONCEPT_REQUIRES to be more
consistent with the current C++0x proposal, which now uses a
"requires" keyword in lieu of "where."

Factored GCC workarounds into the BOOST_CONCEPT_USAGE macro.


[SVN r40769]
This commit is contained in:
Dave Abrahams
2007-11-05 03:54:19 +00:00
parent 6ed3c013bb
commit 7dd50ca8f2
12 changed files with 1293 additions and 1336 deletions

View File

@ -1,13 +1,14 @@
#include <vector>
#include <complex>
#include "algorithm"
int main()
{
std::vector<std::complex<float> > v;
std_::stable_sort(v.begin(), v.end());
}
// (C) Copyright Jeremy Siek 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <list>
#include <algorithm>
int main() {
std::list<int> v;
std::stable_sort(v.begin(), v.end());
return 0;
}

View File

@ -1,312 +1,330 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 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 Check Library</Title>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) 2000 Jeremy Siek and Andrew Lumsdaine, 2007 David Abrahams -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Concept Check Library</title>
<link rel="stylesheet" href="../../rst.css" type="text/css" />
</head>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../boost.png"
ALT="C++ Boost" width="277" height="86">
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<BR Clear>
<h1>The Boost Concept Check Library (BCCL)</h1>
<H1>The Boost Concept Check Library (BCCL)</H1>
<blockquote>
The Concept Check library allows one to add explicit statement and
checking of <a href=
"../../more/generic_programming.html#concept">concepts</a> in the style
of the <a href=
"http://www.generic-programming.org/languages/conceptcpp/specification/">proposed
C++ language extension</a>.
</blockquote>
<h2>
<A NAME="sec:concept-checking"></A>
header <a href="../../boost/concept_check.hpp">
<tt>boost/concept_check.hpp</tt></a>
<br>and <a href="../../boost/concept_archetype.hpp">
<tt>boost/concept_archetype.hpp</tt></a>
</h2>
<h2><a name="sec:concept-checking" id="sec:concept-checking"></a>Synopsis</a></h2>
<p>
Generic programming in C++ is characterized by the use of template
parameters to represent abstract data types (or ``concepts'').
However, the C++ language itself does not provide a mechanism for the
writer of a class or function template to explicitly state what
concept the user-supplied template argument should model (or conform
to). The common practice is to name the template parameter after the
required concept as a hint to the user and to state the concept
requirements in the documentation. However, often times the
requirements are vague, incorrect, or nonexistent, which is quite a
problem for the user, since he or she will not know exactly what kind
of input is expected by the template. Furthermore, the following
problems occur:
<p>Generic programming in C++ is characterized by the use of template
parameters to represent abstract data types (or “<a href=
"../../more/generic_programming.html#concept">concepts</a>”). However, the
C++ language itself does not provide a mechanism for the writer of a class
or function template to explicitly state the concept that the user-supplied
template argument should model (or conform to). Template parameters are
commonly named after the concept they're required to model as a hint to the
user, and to make the concept requirements explicit in code. However, the
compiler doesn't treat these special names specially: a parameter named
<code>RandomAccessIterator</code> is no different to the compiler than one
named <code>T</code>. Furthermore,</p>
<ul>
<li>Compiler error messages resulting from incorrect template
arguments can be particularly difficult to decipher. Often times
the error does not point to the location of the template
call-site, but instead exposes the internals of the template, which
the user should never have to see.</li>
<ul>
<li>Compiler error messages resulting from incorrect template arguments
can be particularly difficult to decipher. Often times the error does not
point to the location of the template call-site, but instead exposes the
internals of the template, which the user should never have to see.</li>
<li>The documented concept requirements may not fully <i>cover</i>
the template, meaning the user could get a compiler error even
though the supplied template arguments meet the documented
requirements.</li>
<li>Without checking from the compiler, the documented requirements are
oftentimes vague, incorrect, or nonexistent, so a user cannot know
exactly what kind of arguments are expected.</li>
<li>The documented concept requirements may be too stringent,
requiring more than is really needed by the template.</li>
<li>The documented concept requirements may not fully <i>cover</i> the
needs of the actual template, meaning the user could get a compiler error
even though the supplied template arguments meet the documented
requirements.</li>
<li>The requirements are not explicitly stated in the code, which
makes the code harder to understand. Also, the code may
get out-of-sync with the documented requirements.</li>
</ul>
<li>The documented concept requirements may be too stringent, requiring
more than is really needed by the template.</li>
The Boost Concept Checking Library provides:
<li>Concept names in code may drift out-of-sync with the documented
requirements.</li>
</ul><p>The Boost Concept Checking Library provides:
<ul>
<li>A mechanism for inserting compile-time checks of template
parameters.</li>
<ul>
<li>A mechanism for inserting compile-time checks on template parameters
at their point of use.</li>
<li>A framework for specifying concept requirements though concept
checking classes.</li>
<li>A framework for specifying concept requirements though concept
checking classes.</li>
<li>A mechanism for verifying that concept requirements cover the template.</li>
<li>A mechanism for verifying that concept requirements cover the
template.</li>
<li>A suite of concept checking classes and archetype classes that
match the concept requirements in the C++ Standard Library.</li>
</ul>
<li>A suite of concept checking classes and archetype classes that match
the concept requirements in the C++ Standard Library.</li>
The mechanisms use standard C++ and introduce no run-time
overhead. The main cost of using the mechanism is in compile-time.
<li>An alternative to the use of traits classes for accessing associated
types that mirrors the syntax proposed for the next C++ standard.</li>
</ul><p>The mechanisms use standard C++ and introduce no run-time overhead.
The main cost of using the mechanism is in compile-time.</p>
<p>
Any programmer writing class or function templates ought to make
concept checking a normal part of their code writing routine. A
concept check should be inserted for each template parameter in a
component's public interface. If the concept is one of the ones from
the Standard Library, then simply use the matching concept checking
class in the BCCL. If not, then write a new concept checking class -
after all, they are typically only a few lines long. For new concepts,
a matching archetype class should also be created, which is a minimal
skeleton-implementation of the concept
<p><strong>Every programmer writing class or function templates ought to
make concept checking a normal part of their code writing routine.</strong>
A concept check should be inserted for each template parameter in a
component's public interface. If the concept is one of the ones from the
Standard Library, then simply use the matching concept checking class in
the BCCL. If not, then write a new concept checking class - after all, they
are typically only a few lines long. For new concepts, a matching archetype
class should also be created, which is a minimal skeleton-implementation of
the concept</p>
<p>
The documentation is organized into the following sections.
<p>The documentation is organized into the following sections.</p>
<OL>
<LI><a href="#introduction">Introduction</a></LI>
<LI><a href="#motivating-example">Motivating Example</a></LI>
<LI><a href="#history">History</a></LI>
<LI><a href="#publications">Publications</a></LI>
<LI><a href="#acknowledgements">Acknowledgements</a></LI>
<LI><a href="./using_concept_check.htm">Using Concept Checks</a></LI>
<LI><a href="creating_concepts.htm">Creating Concept Checking Classes</a></LI>
<LI><a href="./concept_covering.htm">Concept Covering and Archetypes</a></LI>
<LI><a href="./prog_with_concepts.htm" ">Programming With Concepts</a></LI>
<LI><a href="./implementation.htm">Implementation</a></LI>
<LI><a href="./reference.htm">Reference</a></LI>
</OL>
<ol>
<li><a href="#introduction">Introduction</a></li>
<p>
<a href="../../people/jeremy_siek.htm">Jeremy Siek</a> contributed
this library. <a href="../../people/beman_dawes.html">Beman Dawes</a>
managed the formal review.
<li><a href="#motivating-example">Motivating Example</a></li>
<h2><a name="introduction">Introduction</a></h2>
A <i>concept</i> is a set of requirements (valid expressions,
associated types, semantic invariants, complexity guarantees, etc.)
that a type must fulfill to be correctly used as arguments in a call
to a generic algorithm. In C++, concepts are represented by formal
template parameters to function templates (generic algorithms).
However, C++ has no explicit mechanism for representing concepts ---
template parameters are merely placeholders. By convention, these
parameters are given names corresponding to the concept that is
required, but a C++ compiler does not enforce compliance to the
concept when the template parameter is bound to an actual type.
<li><a href="#history">History</a></li>
<p>
Naturally, if a generic algorithm is invoked with a type that does not
fulfill at least the syntactic requirements of the concept, a
compile-time error will occur. However, this error will not <i>per
se</i> reflect the fact that the type did not meet all of the
requirements of the concept. Rather, the error may occur deep inside
the instantiation hierarchy at the point where an expression is not
valid for the type, or where a presumed associated type is not
available. The resulting error messages are largely uninformative and
basically impenetrable.
<li><a href="#publications">Publications</a></li>
<p>
What is required is a mechanism for enforcing ``concept safety'' at
(or close to) the point of instantiation. The Boost Concept Checking
Library uses some standard C++ constructs to enforce early concept
compliance and that provides more informative error messages upon
non-compliance.
<li><a href="#acknowledgements">Acknowledgements</a></li>
<p>
Note that this technique only addresses the syntactic
requirements of concepts (the valid expressions and associated types).
We do not address the semantic invariants or complexity guarantees,
which are also part of concept requirements..
<li><a href="./using_concept_check.htm">Using Concept Checks</a></li>
<h2><a name="motivating-example">Motivating Example</a></h2>
<li><a href="creating_concepts.htm">Creating Concept Checking
Classes</a></li>
We present a simple example to illustrate incorrect usage of a
template library and the resulting error messages. In the code below,
the generic <tt>std::stable_sort()</tt> algorithm from the Standard
Template Library (STL)[<a
href="bibliography.htm#austern99:_gener_progr_stl">3</a>, <a
href="bibliography.htm#IB-H965502">4</a>,<a
href="bibliography.htm#stepa.lee-1994:the.s:TR">5</a>] is applied to
a linked list.
<li><a href="./concept_covering.htm">Concept Covering and
Archetypes</a></li>
<pre>
<li><a href="./prog_with_concepts.htm">Programming With Concepts</a></li>
<li><a href="./implementation.htm">Implementation</a></li>
<li><a href="./reference.htm">Reference</a></li>
</ol>
<p><a href="../../people/jeremy_siek.htm">Jeremy Siek</a> contributed this
library. <a href="../../people/beman_dawes.html">Beman Dawes</a> managed
the formal review. <a href="../../people/dave_abrahams.htm">Dave
Abrahams</a> contributed a rewrite that updated syntax to be more
compatible with proposed syntax for concept support the C++ core
language.</p>
<h2><a name="introduction" id="introduction">Introduction</a></h2><p>A
<i>concept</i> is a set of requirements (valid expressions, associated
types, semantic invariants, complexity guarantees, etc.) that a type must
fulfill to be correctly used as arguments in a call to a generic algorithm.
In C++, concepts are represented by formal template parameters to function
templates (generic algorithms). However, C++ has no explicit mechanism for
representing concepts—template parameters are merely placeholders. By
convention, these parameters are given names corresponding to the concept
that is required, but a C++ compiler does not enforce compliance to the
concept when the template parameter is bound to an actual type.
<p>Naturally, if a generic algorithm is invoked with a type that does not
fulfill at least the syntactic requirements of the concept, a compile-time
error will occur. However, this error will not <i>per se</i> reflect the
fact that the type did not meet all of the requirements of the concept.
Rather, the error may occur deep inside the instantiation hierarchy at the
point where an expression is not valid for the type, or where a presumed
associated type is not available. The resulting error messages are largely
uninformative and basically impenetrable.</p>
<p>What is required is a mechanism for enforcing
“concept safety” at (or close to) the point
of instantiation. The Boost Concept Checking Library uses some standard C++
constructs to enforce early concept compliance and that provides more
informative error messages upon non-compliance.</p>
<p>Note that this technique only addresses the syntactic requirements of
concepts (the valid expressions and associated types). We do not address
the semantic invariants or complexity guarantees, which are also part of
concept requirements..</p>
<h2><a name="motivating-example" id="motivating-example">Motivating
Example</a></h2>
<p>We present a simple example to illustrate incorrect usage of a template
library and the resulting error messages. In the code below, the generic
<tt>std::stable_sort()</tt> algorithm from the Standard Template Library
(STL)[<a href="bibliography.htm#austern99:_gener_progr_stl">3</a>, <a href=
"bibliography.htm#IB-H965502">4</a>,<a href=
"bibliography.htm#stepa.lee-1994:the.s:TR">5</a>] is applied to a linked
list.</p>
<pre>
<a href="./bad_error_eg.cpp">bad_error_eg.cpp</a>:
1 #include &lt;list&gt;
2 #include &lt;algorithm&gt;
3
4 int main(int, char*[]) {
5 std::list&lt;int&gt; v;
6 std::stable_sort(v.begin(), v.end());
7 return 0;
8 }
<font color="gray">1</font> #include &lt;vector&gt;
<font color="gray">2</font color="gray"> #include &lt;complex&gt;
<font color="gray">3</font color="gray"> #include &lt;algorithm&gt;
<font color="gray">4</font color="gray">
<font color="gray">5</font color="gray"> int main()
<font color="gray">6</font color="gray"> {
<font color="gray">7</font color="gray"> std::vector&lt;std::complex&lt;float&gt; &gt; v;
<font color="gray">8</font color="gray"> std::stable_sort(v.begin(), v.end());
<font color="gray">9</font color="gray"> }
</pre>
Here, the
<tt>std::stable_sort()</tt> algorithm is prototyped as follows:
<pre>
<p>Here, the <tt>std::stable_sort()</tt> algorithm is prototyped as
follows:</p>
<pre>
template &lt;class RandomAccessIterator&gt;
void stable_sort(RandomAccessIterator first, RandomAccessIterator last);
</pre>
Attempting to compile this code with Gnu C++ produces the following
compiler error. The output from other compilers is listed in the
Appendix.
<pre>
stl_algo.h: In function `void __merge_sort_loop&lt;_List_iterator
&lt;int,int &amp;,int *&gt;, int *, int&gt;(_List_iterator&lt;int,int &amp;,int *&gt;,
_List_iterator&lt;int,int &amp;,int *&gt;, int *, int)':
stl_algo.h:1448: instantiated from `__merge_sort_with_buffer
&lt;_List_iterator&lt;int,int &amp;,int *&gt;, int *, int&gt;(
_List_iterator&lt;int,int &amp;,int *&gt;, _List_iterator&lt;int,int &amp;,int *&gt;,
int *, int *)'
stl_algo.h:1485: instantiated from `__stable_sort_adaptive&lt;
_List_iterator&lt;int,int &amp;,int *&gt;, int *, int&gt;(_List_iterator
&lt;int,int &amp;,int *&gt;, _List_iterator&lt;int,int &amp;,int *&gt;, int *, int)'
stl_algo.h:1524: instantiated from here
stl_algo.h:1377: no match for `_List_iterator&lt;int,int &amp;,int *&gt; &amp; -
_List_iterator&lt;int,int &amp;,int *&gt; &amp;'
<p>Attempting to compile this code with Gnu C++ produces the following
compiler error:</p>
<pre>
/usr/include/c++/4.1.2/bits/stl_algo.h: In function void std::
__insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with
_RandomAccessIterator = __gnu_cxx::__normal_iterator&lt;std::complex&lt;float
&gt;*, std::vector&lt;std::complex&lt;float&gt;, std::allocator&lt;std::complex&lt;
float&gt; &gt; &gt; &gt;]:
/usr/include/c++/4.1.2/bits/stl_algo.h:3066: instantiated from void
std::__inplace_stable_sort(_RandomAccessIterator,
_RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::
__normal_iterator&lt;std::complex&lt;float&gt;*, std::vector&lt;std::complex&lt;
float&gt;, std::allocator&lt;std::complex&lt;float&gt; &gt; &gt; &gt;]
/usr/include/c++/4.1.2/bits/stl_algo.h:3776: instantiated from void
std::stable_sort(_RandomAccessIterator, _RandomAccessIterator) [with
_RandomAccessIterator = __gnu_cxx::__normal_iterator&lt;std::complex&lt;float
&gt;*, std::vector&lt;std::complex&lt;float&gt;, std::allocator&lt;std::complex&lt;
float&gt; &gt; &gt; &gt;]
bad_error_eg.cpp:8: instantiated from here
/usr/include/c++/4.1.2/bits/stl_algo.h:2277: error: no match for
operator&lt; in __val &lt; __first. __gnu_cxx::__normal_iterator&lt;
_Iterator, _Container&gt;::operator* [with _Iterator = std::complex&lt;float
&gt;*, _Container = std::vector&lt;std::complex&lt;float&gt;, std::allocator&lt;
std::complex&lt;float&gt; &gt; &gt;]()
</pre>
In this case, the fundamental error is that
<tt>std:list::iterator</tt> does not model the concept of <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a>. The list iterator is only bidirectional, not
fully random access (as would be a vector iterator). Unfortunately,
there is nothing in the error message to indicate this to the user.
<p>In this case, the fundamental error is
that <tt>std:complex&lt;float&gt;</tt> does not model the <a href=
"http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a>
concept. Unfortunately, there is nothing in the error message to
indicate that to the user.</p>
<p>
To a C++ programmer having enough experience with template libraries
the error may be obvious. However, for the uninitiated, there are several
reasons why this message would be hard to understand.
<p>The error may be obvious to a C++ programmer having enough
experience with template libraries, but there are several reasons
why this message could be hard for the uninitiated to
understand:</p>
<OL>
<LI> The location of the error, line 6 of <tt>bad_error_eg.cpp</tt>
is not pointed to by the error message, despite the fact that Gnu C++
prints up to 4 levels deep in the instantiation stack.
<LI> There is no textual correlation between the error message and the
documented requirements for <tt>std::stable_sort()</tt> and for
<a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a>.
<LI> The error message is overly long, listing functions internal
to the STL that the user does not (and should not!) know or care
about.
<LI> With so many internal library functions listed in the error
message, the programmer could easily infer that the error is due
to the library, rather than to his or her own code.
</OL>
<ol>
<li>There is no textual correlation between the error message and the
documented requirements for <tt>std::stable_sort()</tt> and for <a href=
"http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a>.</li>
The following is an example of what we might expect from a more
informative message (and is in fact what the Boost Concept Checking
Library produces):
<li>The error message is overly long, listing functions internal
to the STL (e.g. <code>__insertion_sort</code>) that the user
does not (and should not!) know or care about.</li>
<pre>
boost/concept_check.hpp: In method `void LessThanComparableConcept
&lt;_List_iterator&lt;int,int &amp;,int *&gt; &gt;::~LessThanComparableConcept()':
boost/concept_check.hpp:334: instantiated from `RandomAccessIteratorConcept
&lt;_List_iterator&lt;int,int &amp;,int *&gt; &gt;::~RandomAccessIteratorConcept()'
bad_error_eg.cpp:6: instantiated from `stable_sort&lt;_List_iterator
&lt;int,int &amp;,int *&gt; &gt;(_List_iterator&lt;int,int &amp;,int *&gt;,
_List_iterator&lt;int,int &amp;,int *&gt;)'
boost/concept_check.hpp:209: no match for `_List_iterator&lt;int,int &amp;,int *&gt; &amp;
&lt; _List_iterator&lt;int,int &amp;,int *&gt; &amp;'
<li>With so many internal library functions listed in the error message,
the programmer could easily infer that the problem is in the library,
rather than in his or her own code.</li>
</ol>
<p>The following is an example of what we might expect from a more
informative message (and is in fact what the Boost Concept Checking Library
produces):</p>
<pre>
boost/concept_check.hpp: In destructor boost::LessThanComparable&lt;TT&gt;::~
LessThanComparable() [with TT = std::complex&lt;float&gt;]:
boost/concept/detail/general.hpp:29: instantiated from static void boost::
concept::requirement&lt;Model&gt;::failed() [with Model = boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;]
boost/concept/requires.hpp:30: instantiated from boost::_requires_&lt;void
(*)(boost::LessThanComparable&lt;std::complex&lt;float&gt; &gt;)&gt;
bad_error_eg.cpp:8: instantiated from here
boost/concept_check.hpp:236: error: no match for operator&lt; in ((boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;*)this)-&gt;boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;::a &lt; ((boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;*)this)-&gt;boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;::b
</pre>
This message rectifies several of the shortcomings of the standard
error messages.
<p>This message rectifies several of the shortcomings of the standard error
messages.</p>
<UL>
<LI> The location of the error, <tt>bad_error_eg.cpp:6</tt> is
specified in the error message.
<LI> The message refers explicitly to concepts that the user can look
up in the STL documentation (<a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a>).
<LI> The error message is now much shorter and does not reveal
internal STL functions.
<LI> The presence of <tt>concept_check.hpp</tt> in the error message
alerts the user to the fact that the error lies in the user code and
not in the library implementation.
</UL>
<ul>
<li>The message refers explicitly to concepts that the user can look up
in the STL documentation (<a href=
"http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a>).</li>
<h2><a name="history">History</a></h2>
<li>The error message is now much shorter and does not reveal
internal STL functions, nor indeed does it even point
to <code>std::stable_sort</code>.</li>
An earlier version of this concept checking system was developed by
the author while working at SGI in their C++ compiler and library
group. The earlier version is now part of the SGI STL distribution. The
boost concept checking library differs from the concept checking in
the SGI STL in that the definition of concept checking classes has
been greatly simplified, at the price of less helpful verbiage in the
error messages.
<li>The presence of <tt>concept_check.hpp</tt> in the error message
alerts the user to the fact that the error lies in the user code and not
in the library implementation.</li>
</ul>
<h2><a name="publications">Publications</a></h2>
<h2><a name="history" id="history">History</a></h2>
<ul>
<li><a href="http://www.oonumerics.org/tmpw00/">
C++ Template Workshop 2000</a>, Concept Checking</li>
</ul>
<p>The first version of this concept checking system was developed
by Jeremy Siek while working at SGI in their C++ compiler and
library group. That version is now part of the SGI STL
distribution. The system originally introduced as the boost concept
checking library differs from concept checking in the SGI STL in
that the definition of concept checking classes was greatly
simplified, at the price of less helpful verbiage in the error
messages. In 2006 the system was rewritten (preserving backward
compatibility) by Dave Abrahams to be easier to use, more similar to
the proposed concept support the C++ core language, and to give
better error messages.
</p>
<h2><a name="acknowledgements">Acknowledgements</a></h2>
<h2><a name="publications" id="publications">Publications</a></h2>
The idea to use function pointers to cause instantiation is due to
Alexander Stepanov. I am not sure of the origin of the idea to use
expressions to do up-front checking of templates, but it did appear in
D&amp;E[
<a href="bibliography.htm#stroustrup94:_design_evolution">2</a>].
Thanks to Matt Austern for his excellent documentation and
organization of the STL concepts, upon which these concept checks
are based. Thanks to Boost members for helpful comments and
reviews.
<ul>
<li><a href="http://www.oonumerics.org/tmpw00/">C++ Template Workshop
2000</a>, Concept Checking</li>
</ul>
<h2><a name="acknowledgements" id=
"acknowledgements">Acknowledgements</a></h2><p>The idea to use function
pointers to cause instantiation is due to Alexander Stepanov. We are not sure
of the origin of the idea to use expressions to do up-front checking of
templates, but it did appear in D&amp;E[ <a href=
"bibliography.htm#stroustrup94:_design_evolution">2</a>]. Thanks to Matt
Austern for his excellent documentation and organization of the STL
concepts, upon which these concept checks are based. Thanks to Boost
members for helpful comments and reviews.
<p>
<a href="./using_concept_check.htm">Next: Using Concept Checks</a>
<p><a href="./using_concept_check.htm">Next: Using Concept
Checks</a><br /></p>
<hr />
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
</BODY>
</HTML>
<td><a href="../../people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
</td>
</tr>
</table>
</body>
</html>

View File

@ -1,126 +1,125 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 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 Covering and Archetypes</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../boost.png"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<h2><a name="concept-covering">Concept Covering and Archetypes</a></h2>
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
We have discussed how it is important to select the minimal
requirements (concepts) for the inputs to a component, but it is
equally important to verify that the chosen concepts <i>cover</i> the
algorithm. That is, any possible user error should be caught by the
concept checks and not let slip through. Concept coverage can be
verified through the use of <i>archetype classes</i>. An archetype
class is an exact implementation of the interface associated with a
particular concept. The run-time behavior of the archetype class is
not important, the functions can be left empty. A simple test program
can then be compiled with the archetype classes as the inputs to the
component. If the program compiles then one can be sure that the
concepts cover the component.
<title>Concept Covering and Archetypes</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../../rst.css" type="text/css" />
</head>
The following code shows the archetype class for the <a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a> concept. Some care must be taken to ensure that the
archetype is an exact match to the concept. For example, the concept
states that the return type of <tt>operator*()</tt> must be
convertible to the value type. It does not state the more stringent
requirement that the return type be <tt>T&amp;</tt> or <tt>const
T&amp;</tt>. That means it would be a mistake to use <tt>T&amp;</tt>
or <tt>const T&amp;</tt> for the return type of the archetype
class. The correct approach is to create an artificial return type
that is convertible to <tt>T</tt>, as we have done here with
<tt>reference</tt>. The validity of the archetype class test is
completely dependent on it being an exact match with the concept,
which must be verified by careful (manual) inspection.
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<pre>
template &lt;class T&gt;
class input_iterator_archetype
{
private:
typedef input_iterator_archetype self;
public:
typedef std::input_iterator_tag iterator_category;
typedef T value_type;
struct reference {
operator const value_type&amp;() const { return static_object&lt;T&gt;::get(); }
};
typedef const T* pointer;
typedef std::ptrdiff_t difference_type;
self&amp; operator=(const self&amp;) { return *this; }
bool operator==(const self&amp;) const { return true; }
bool operator!=(const self&amp;) const { return true; }
reference operator*() const { return reference(); }
self&amp; operator++() { return *this; }
self operator++(int) { return *this; }
<h2><a name="concept-covering" id="concept-covering">Concept Covering and
Archetypes</a></h2>
<p>We have discussed how it is important to select the minimal requirements
(concepts) for the inputs to a component, but it is equally important to
verify that the chosen concepts <i>cover</i> the algorithm. That is, any
possible user error should be caught by the concept checks and not let slip
through. Concept coverage can be verified through the use of <i>archetype
classes</i>. An archetype class is an exact implementation of the interface
associated with a particular concept. The run-time behavior of the
archetype class is not important, the functions can be left empty. A simple
test program can then be compiled with the archetype classes as the inputs
to the component. If the program compiles then one can be sure that the
concepts cover the component. The following code shows the archetype class
for the <a href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a> concept. Some care must be taken to ensure that the archetype
is an exact match to the concept. For example, the concept states that the
return type of <tt>operator*()</tt> must be convertible to the value type.
It does not state the more stringent requirement that the return type be
<tt>T&amp;</tt> or <tt>const T&amp;</tt>. That means it would be a mistake
to use <tt>T&amp;</tt> or <tt>const T&amp;</tt> for the return type of the
archetype class. The correct approach is to create an artificial return
type that is convertible to <tt>T</tt>, as we have done here with
<tt>reference</tt>. The validity of the archetype class test is completely
dependent on it being an exact match with the concept, which must be
verified by careful (manual) inspection.</p>
<pre>
template &lt;class T&gt;
class input_iterator_archetype
{
private:
typedef input_iterator_archetype self;
public:
typedef std::input_iterator_tag iterator_category;
typedef T value_type;
struct reference {
operator const value_type&amp;() const { return static_object&lt;T&gt;::get(); }
};
typedef const T* pointer;
typedef std::ptrdiff_t difference_type;
self&amp; operator=(const self&amp;) { return *this; }
bool operator==(const self&amp;) const { return true; }
bool operator!=(const self&amp;) const { return true; }
reference operator*() const { return reference(); }
self&amp; operator++() { return *this; }
self operator++(int) { return *this; }
};
</pre>
Generic algorithms are often tested by being instantiated with a
number of common input types. For example, one might apply
<tt>std::stable_sort()</tt> with basic pointer types as the iterators.
Though appropriate for testing the run-time behavior of the algorithm,
this is not helpful for ensuring concept coverage because C++ types
never match particular concepts, they often provide much more than the
minimal functionality required by any one concept. That is, even
though the function template compiles with a given type, the concept
requirements may still fall short of covering the functions actual
requirements. This is why it is important to compile with archetype
classes in addition to testing with common input types.
<p>Generic algorithms are often tested by being instantiated with a number
of common input types. For example, one might apply
<tt>std::stable_sort()</tt> with basic pointer types as the iterators.
Though appropriate for testing the run-time behavior of the algorithm, this
is not helpful for ensuring concept coverage because C++ types never match
particular concepts exactly. Instead, they often provide more than the
minimal functionality required by any one concept. Even though the function
template has concept checks, and compiles with a given type, the checks may
still fall short of covering all the functionality that is actually used.
This is why it is important to compile with archetype classes in addition
to testing with common input types.</p>
<p>
The following is an excerpt from <a
href="./stl_concept_covering.cpp"><tt>stl_concept_covering.cpp</tt></a>
that shows how archetypes can be used to check the requirement
documentation for
<a href="http://www.sgi.com/tech/stl/stable_sort.html">
<tt>std::stable_sort()</tt></a>. In this case, it looks like the <a
href="../utility/CopyConstructible.html">CopyConstructible</a> and <a
href="../utility/Assignable.html">Assignable</a> requirements were
forgotten in the SGI STL documentation (try removing those
archetypes). The Boost archetype classes have been designed so that
they can be layered. In this example the value type of the iterator
is composed out of three archetypes. In the archetype class reference
below, template parameters named <tt>Base</tt> indicate where the
layered archetype can be used.
<pre>
{
typedef less_than_comparable_archetype&lt;
sgi_assignable_archetype&lt;&gt; &gt; ValueType;
random_access_iterator_archetype&lt;ValueType&gt; ri;
std::stable_sort(ri, ri);
}
<p>The following is an excerpt from <a href=
"./stl_concept_covering.cpp"><tt>stl_concept_covering.cpp</tt></a> that
shows how archetypes can be used to check the requirement documentation for
<a href=
"http://www.sgi.com/tech/stl/stable_sort.html"><tt>std::stable_sort()</tt></a>.
In this case, it looks like the <a href=
"../utility/CopyConstructible.html">CopyConstructible</a> and <a href=
"../utility/Assignable.html">Assignable</a> requirements were forgotten in
the SGI STL documentation (try removing those archetypes). The Boost
archetype classes have been designed so that they can be layered. In this
example the value type of the iterator is composed out of three archetypes.
In the <a href="reference.htm#basic-archetype">archetype class
reference</a>, template parameters named <tt>Base</tt> indicate where the
layered archetype paradigm can be used.</p>
<pre>
{
typedef less_than_comparable_archetype&lt;
sgi_assignable_archetype&lt;&gt; &gt; ValueType;
random_access_iterator_archetype&lt;ValueType&gt; ri;
std::stable_sort(ri, ri);
}
</pre>
<a href="./prog_with_concepts.htm">Next: Programming with Concepts</a><br>
<a href="./creating_concepts.htm">Prev: Creating Concept Checking Classes</a>
<p><a href="./prog_with_concepts.htm">Next: Programming with
Concepts</a><br />
<a href="./creating_concepts.htm">Prev: Creating Concept Checking
Classes</a><br />
<hr />
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
</BODY>
</HTML>
<td><a href="../../people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
</tr>
</table>
</body>
</html>

View File

@ -1,110 +1,157 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 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>Creating Concept Checking Classes</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../boost.png"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
<h2><a name="creating-concept-checks">Creating Concept Checking Classes</a></h2>
<title>Creating Concept Checking Classes</title>
<link rel="stylesheet" href="../../rst.css" type="text/css" />
</head>
As an example of how to create a concept checking class, we look
at how to create the corresponding checks for the
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a> concept. First, as a convention we name the
concept checking class after the concept, and add the suffix
``<tt>Concept</tt>''. Next we must define a member function named
<tt>constraints()</tt> in which we will exercise the valid expressions
of the concept. <tt>function_requires()</tt> expects this function's
signature to appear exactly as it is appears below: a <tt>void</tt>
non-const member function with no parameters.
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<p>
The first part of the <tt>constraints()</tt> function includes
the requirements that correspond to the <i>refinement</i> relationship
between <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a> and the concepts which it builds upon:
<a href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">
BidirectionalIterator</a> and
<a href="http://www.sgi.com/tech/stl/LessThanComparable.html">
LessThanComparable</a>. We could have instead used
<tt>BOOST_CLASS_REQUIRE</tt> and placed these requirements in the class
body, however <tt>BOOST_CLASS_REQUIRE</tt> uses C++ language features that
are less portable.
<h2><a name="creating-concept-checks" id="creating-concept-checks">Creating
Concept Checking Classes</a></h2>
<p>
Next we check that the <tt>iterator_category</tt> of the iterator is
either <tt>std::random_access_iterator_tag</tt> or a derived class.
After that we write out some code that corresponds to the valid
expressions of the <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a> concept. Typedefs can also be added to
enforce the associated types of the concept.
<p>As an example of how to create a concept checking class template, we
look at how to create the corresponding checks for the <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> concept.
The complete definition is here:</p>
<pre>
template &lt;class X&gt;
struct InputIterator
: Assignable&lt;X&gt;, EqualityComparable&lt;X&gt;
{
private:
typedef std::iterator_traits&lt;X&gt; t;
public:
typedef typename t::value_type value_type;
typedef typename t::difference_type difference_type;
typedef typename t::reference reference;
typedef typename t::pointer pointer;
typedef typename t::iterator_category iterator_category;
<pre>
template &lt;class Iter&gt;
struct RandomAccessIteratorConcept
{
void constraints() {
function_requires&lt; BidirectionalIteratorConcept&lt;Iter&gt; &gt;();
function_requires&lt; LessThanComparableConcept&lt;Iter&gt; &gt;();
function_requires&lt; ConvertibleConcept&lt;
typename std::iterator_traits&lt;Iter&gt;::iterator_category,
std::random_access_iterator_tag&gt; &gt;();
i += n;
i = i + n; i = n + i;
i -= n;
i = i - n;
n = i - j;
i[n];
BOOST_CONCEPT_ASSERT((SignedInteger&lt;difference_type&gt;));
BOOST_CONCEPT_ASSERT((Convertible&lt;iterator_category, std::input_iterator_tag&gt;));
BOOST_CONCEPT_USAGE(InputIterator)
{
X j(i); <font color=
"green">// require copy construction</font>
same_type(*i++,v); <font color=
"green">// require postincrement-dereference returning value_type</font>
X&amp; x = ++j; <font color=
"green">// require preincrement returning X&amp;</font>
}
Iter i, j;
typename std::iterator_traits&lt;Iter&gt;::difference_type n;
};
private:
X i;
value_type v;
<font color=
"green">// Type deduction will fail unless the arguments have the same type.</font>
template &lt;typename T&gt;
void same_type(T const&amp;, T const&amp;);
};
</pre>
<h3>Walkthrough</h3>
<p>First, as a convention we name the concept checking class after the
concept. Next, since InputIterator is a refinement of Assignable and
EqualityComparable, we derive its concept checking class from the checking
classes for those other concepts. The library will automatically check for
conformance to Assignable and EqualityComparable whenever it checks the
InputIterator concept.</p>
<p>Next, we declare the concept's <a href=
"../../more/generic_programming.html#associated_type">associated types</a>
as member typedefs. The associated difference type is required to be a
signed integer, and the iterator category has to be convertible to
std::input_iterator_tag, so we assert those relationships. The syntax for
accessing associated types through the concept-checking template mirrors
the <a href=
"http://www.generic-programming.org/languages/conceptcpp/">proposed</a>
syntax for associated type access in C++0x Finally, we use the
<code>BOOST_CONCEPT_USAGE</code> macro to declare the function that
exercises all the concept's valid expressions. Note that at this point you
may sometimes need to be a little creative: for example, to check that
<code>*i++</code> returns the iterator's value type, we pass both values to
the <code>same_type</code> member function template, which requires both
arguments to have the same type, modulo references and cv-qualification.
It's an imperfect check, but it's better than nothing.</p>
<h3>Values for Usage Patterns Should Be Data Members</h3>
<p>You may be wondering why we declared <code>i</code> and <code>v</code>
as data members in the example above. Why didn't we simply write the
following?</p>
<pre>
BOOST_CONCEPT_USAGE(InputIterator)
{
X i; <font color=
"green">// create the values we need</font>
value_type v;
X j(i); <font color=
"green">// require copy construction</font>
same_type(*i++,v); <font color=
"green">// require postincrement-dereference returning value_type</font>
X&amp; x = ++j; <font color=
"green">// require preincrement returning X&amp;</font>
}
</pre>
One potential pitfall in designing concept checking classes is using
more expressions in the constraint function than necessary. For
example, it is easy to accidentally use the default constructor to
create the objects that will be needed in the expressions (and not all
concepts require a default constructor). This is the reason we write
the constraint function as a member function of a class. The objects
involved in the expressions are declared as data members of the class.
Since objects of the constraints class template are never
instantiated, the default constructor for the concept checking class
is never instantiated. Hence the data member's default constructors
are never instantiated (C++ Standard Section 14.7.1 9).
<p>Unfortunately, that code wouldn't have worked out so well, because it
unintentionally imposes the requirement that <code>X</code> and its value
type are both default-constructible. On the other hand, since instances of
the <code>InputIterator</code> template will never be constructed, the
compiler never has to check how its data members will be constructed (C++
Standard Section 14.7.1 9). For that reason you should <strong>always
declare values needed for usage patterns as data members</strong>.</p>
<p>
<a href="./concept_covering.htm">Next: Concept Covering and Archetypes</a><br>
<a href="./using_concept_check.htm">Prev: Using Concept Checks</a>
<p>These sorts of errors in concept definitions can be detected by the use
of <a href="concept_covering.htm">Concept Archetypes</a>, but it's always
better to avoid them pre-emptively.</p>
<h3>Similarity to Proposed C++0x Language Support for Concepts</h3>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
<p>This library's syntaxes for concept refinement and for access of
associated types mirrors the corresponding <a href=
"http://www.generic-programming.org/languages/conceptcpp/">proposed</a>
syntaxes in C++0x. However, C++0x will use
“signatures” rather than usage patterns to
describe the valid operations on types participating in a concept, so when
converting your concept checking classes into language-supported concepts,
you'll need to translate your usage function into a series of
signatures.</p>
</BODY>
</HTML>
<p><a href="./concept_covering.htm">Next: Concept Covering and
Archetypes</a><br />
<a href="./using_concept_check.htm">Prev: Using Concept
Checks</a><br /></p>
<hr />
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
<td><a href="../../people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
</tr>
</table>
</body>
</html>

View File

@ -13,7 +13,7 @@ namespace fake
using namespace boost;
template<typename RanIter>
BOOST_CONCEPT_WHERE(
BOOST_CONCEPT_REQUIRES(
((Mutable_RandomAccessIterator<RanIter>))
((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>))

View File

@ -1,50 +1,59 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 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 Implementation</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../boost.png"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000, David Abrahams 2007 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../../rst.css" type="text/css" />
<h2><a name="implementation">Implementation</a></h2>
<title>Concept Checking Implementation</title>
</head>
Ideally we would like to catch, and indicate, the concept violation at
the point of instantiation. As mentioned in D&amp;E[<a
href="bibliography.htm#stroustrup94:_design_evolution">2</a>], the error
can be caught by exercising all of the requirements needed by the
function template. Exactly how the requirements (the valid
expressions in particular) are exercised is a tricky issue, since we
want the code to be compiled --- <i>but not executed</i>. Our
approach is to exercise the requirements in a separate function that
is assigned to a function pointer. In this case, the compiler will
instantiate the function but will not actually invoke it. In
addition, an optimizing compiler will remove the pointer assignment as
``dead code'' (though the run-time overhead added by the assignment
would be trivial in any case). It might be conceivable for a compiler
to skip the semantic analysis and compilation of the constraints
function in the first place, which would make our function pointer
technique ineffective. However, this is unlikely because removal of
unnecessary code and functions is typically done in later stages of a
compiler. We have successfully used the function pointer technique
with GNU C++, Microsoft Visual C++, and several EDG-based compilers
(KAI C++, SGI MIPSpro). The following code shows how this technique
can be applied to the <tt>std::stable_sort()</tt> function:
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<pre>
<h2><a name="warning" id="warning"><font color=
"red">Warning</font></a></h2>
<p><font color="red">This documentation is out-of-date; similar but
newer implementation techniques are now used. This documentation
also refers to components and protocols in the library's old
interace such as <code>BOOST_CLASS_REQUIRES</code>
and <code>constraints()</code> functions, which are still supported
but deprecated.</font></p>
<h2><a name="implementation" id="implementation">Implementation</a></h2>
<p>Ideally we would like to catch, and indicate, the concept violation at
the point of instantiation. As mentioned in D&amp;E[<a href=
"bibliography.htm#stroustrup94:_design_evolution">2</a>], the error can be
caught by exercising all of the requirements needed by the function
template. Exactly how the requirements (the valid expressions in
particular) are exercised is a tricky issue, since we want the code to be
compiled—<i>but not executed</i>. Our approach is to exercise the
requirements in a separate function that is assigned to a function pointer.
In this case, the compiler will instantiate the function but will not
actually invoke it. In addition, an optimizing compiler will remove the
pointer assignment as ``dead code'' (though the run-time overhead added by
the assignment would be trivial in any case). It might be conceivable for a
compiler to skip the semantic analysis and compilation of the constraints
function in the first place, which would make our function pointer
technique ineffective. However, this is unlikely because removal of
unnecessary code and functions is typically done in later stages of a
compiler. We have successfully used the function pointer technique with GNU
C++, Microsoft Visual C++, and several EDG-based compilers (KAI C++, SGI
MIPSpro). The following code shows how this technique can be applied to the
<tt>std::stable_sort()</tt> function:</p>
<pre>
template &lt;class RandomAccessIterator&gt;
void stable_sort_constraints(RandomAccessIterator i)
{
@ -57,24 +66,23 @@ can be applied to the <tt>std::stable_sort()</tt> function:
void stable_sort(RandomAccessIterator first, RandomAccessIterator last)
{
typedef void (*fptr_type)(RandomAccessIterator);
fptr_type x = &stable_sort_constraints;
fptr_type x = &amp;stable_sort_constraints;
...
}
</pre>
There is often a large set of requirements that need to be checked,
and it would be cumbersome for the library implementor to write
constraint functions like <tt>stable_sort_constraints()</tt> for every
public function. Instead, we group sets of valid expressions
together, according to the definitions of the corresponding concepts.
For each concept we define a concept checking class template where the
template parameter is for the type to be checked. The class contains
a <tt>contraints()</tt> member function which exercises all of the
valid expressions of the concept. The objects used in the constraints
function, such as <tt>n</tt> and <tt>i</tt>, are declared as data
members of the concept checking class.
<pre>
<p>There is often a large set of requirements that need to be checked, and
it would be cumbersome for the library implementor to write constraint
functions like <tt>stable_sort_constraints()</tt> for every public
function. Instead, we group sets of valid expressions together, according
to the definitions of the corresponding concepts. For each concept we
define a concept checking class template where the template parameter is
for the type to be checked. The class contains a <tt>contraints()</tt>
member function which exercises all of the valid expressions of the
concept. The objects used in the constraints function, such as <tt>n</tt>
and <tt>i</tt>, are declared as data members of the concept checking
class.</p>
<pre>
template &lt;class Iter&gt;
struct RandomAccessIteratorConcept
{
@ -90,18 +98,14 @@ members of the concept checking class.
};
</pre>
We can still use the function pointer mechanism to cause instantiation
of the constraints function, however now it will be a member function
pointer. To make it easy for the library implementor to invoke the
concept checks, we wrap the member function pointer mechanism in a
function named <tt>function_requires()</tt>. The following code
snippet shows how to use <tt>function_requires()</tt> to make sure
that the iterator is a
<a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a>.
<pre>
<p>We can still use the function pointer mechanism to cause instantiation
of the constraints function, however now it will be a member function
pointer. To make it easy for the library implementor to invoke the concept
checks, we wrap the member function pointer mechanism in a function named
<tt>function_requires()</tt>. The following code snippet shows how to use
<tt>function_requires()</tt> to make sure that the iterator is a <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>.</p>
<pre>
template &lt;class Iter&gt;
void stable_sort(Iter first, Iter last)
{
@ -110,16 +114,15 @@ RandomAccessIterator</a>.
}
</pre>
The definition of the <tt>function_requires()</tt> is as follows. The
<tt>Concept</tt> is the concept checking class that has been
instantiated with the modeling type. We assign the address of the
constraints member function to the function pointer <tt>x</tt>, which
causes the instantiation of the constraints function and checking of
the concept's valid expressions. We then assign <tt>x</tt> to
<tt>x</tt> to avoid unused variable compiler warnings, and wrap
everything in a do-while loop to prevent name collisions.
<pre>
<p>The definition of the <tt>function_requires()</tt> is as follows. The
<tt>Concept</tt> is the concept checking class that has been instantiated
with the modeling type. We assign the address of the constraints member
function to the function pointer <tt>x</tt>, which causes the instantiation
of the constraints function and checking of the concept's valid
expressions. We then assign <tt>x</tt> to <tt>x</tt> to avoid unused
variable compiler warnings, and wrap everything in a do-while loop to
prevent name collisions.</p>
<pre>
template &lt;class Concept&gt;
void function_requires()
{
@ -128,17 +131,16 @@ everything in a do-while loop to prevent name collisions.
}
</pre>
To check the type parameters of class templates, we provide the
<tt>BOOST_CLASS_REQUIRE</tt> macro which can be used inside the body of a
class definition (whereas <tt>function_requires()</tt> can only be used
inside of a function body). This macro declares a nested class
template, where the template parameter is a function pointer. We then
use the nested class type in a typedef with the function pointer type
of the constraint function as the template argument. We use the
<tt>type_var</tt> and <tt>concept</tt> names in the nested class and
typedef names to help prevent name collisions.
<pre>
<p>To check the type parameters of class templates, we provide the
<tt>BOOST_CLASS_REQUIRE</tt> macro which can be used inside the body of a
class definition (whereas <tt>function_requires()</tt> can only be used
inside of a function body). This macro declares a nested class template,
where the template parameter is a function pointer. We then use the nested
class type in a typedef with the function pointer type of the constraint
function as the template argument. We use the <tt>type_var</tt> and
<tt>concept</tt> names in the nested class and typedef names to help
prevent name collisions.</p>
<pre>
#define BOOST_CLASS_REQUIRE(type_var, ns, concept) \
typedef void (ns::concept &lt;type_var&gt;::* func##type_var##concept)(); \
template &lt;func##type_var##concept _Tp1&gt; \
@ -148,14 +150,12 @@ typedef names to help prevent name collisions.
concept_checking_typedef_##type_var##concept
</pre>
In addition, there are versions of <tt>BOOST_CLASS_REQUIRE</tt> that
take more arguments, to handle concepts that include interactions
between two or more types. <tt>BOOST_CLASS_REQUIRE</tt> was not used
in the implementation of the BCCL concept checks because some
compilers do not implement template parameters of function pointer
type.
<!-- We decided not to go with this version since it is easier to misuse
<p>In addition, there are versions of <tt>BOOST_CLASS_REQUIRE</tt> that
take more arguments, to handle concepts that include interactions between
two or more types. <tt>BOOST_CLASS_REQUIRE</tt> was not used in the
implementation of the BCCL concept checks because some compilers do not
implement template parameters of function pointer type.
<!-- We decided not to go with this version since it is easier to misuse
To check the type parameters of class templates, we provide the
<tt>class_requires</tt> class which can be used inside the body of a
@ -184,21 +184,22 @@ Boost Concept Checking Library concept checks because several
compilers do not implement template parameters of function pointer
type.
-->
--></p>
<p>
<a href="./reference.htm">Next: Reference</a><br>
<a href="prog_with_concepts.htm">Prev: Programming With Concepts</a>
<p><a href="./reference.htm">Next: Reference</a><br />
<a href="prog_with_concepts.htm">Prev: Programming With
Concepts</a><br /></p>
<hr />
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
</BODY>
</HTML>
<td><a href="../../people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
</tr>
</table>
</body>
</html>

View File

@ -21,9 +21,20 @@ struct usage_requirements
~usage_requirements() { ((Model*)0)->~Model(); }
};
# define BOOST_CONCEPT_USAGE(model) \
BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements<model>)); \
~model()
# if BOOST_WORKAROUND(__GNUC__, <= 3)
# define BOOST_CONCEPT_USAGE(model) \
model(); /* at least 2.96 and 3.4.3 both need this :( */ \
BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements<model>)); \
~model()
# else
# define BOOST_CONCEPT_USAGE(model) \
BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements<model>)); \
~model()
# endif
# endif

View File

@ -1,8 +1,8 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_WHERE_DWA2006430_HPP
# define BOOST_CONCEPT_WHERE_DWA2006430_HPP
#ifndef BOOST_CONCEPT_REQUIRES_DWA2006430_HPP
# define BOOST_CONCEPT_REQUIRES_DWA2006430_HPP
# include <boost/parameter/aux_/parenthesized_type.hpp>
# include <boost/concept/assert.hpp>
@ -12,7 +12,7 @@ namespace boost {
// Template for use in handwritten assertions
template <class Model, class More>
struct where_ : More
struct requires_ : More
{
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
typedef typename More::type type;
@ -23,41 +23,52 @@ struct where_ : More
// Template for use by macros, where models must be wrapped in parens.
// This isn't in namespace detail to keep extra cruft out of resulting
// error messages.
template <class ModelFn, class More>
struct _where_ : More
template <class ModelFn>
struct _requires_
{
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
typedef typename More::type type;
# endif
enum { value = 0 };
BOOST_CONCEPT_ASSERT_FN(ModelFn);
};
#define BOOST_CONCEPT_WHERE_OPEN(r,data,t) ::boost::_where_<void(*)t,
#define BOOST_CONCEPT_WHERE_CLOSE(r,data,t) >
template <int check, class Result>
struct Requires_ : ::boost::parameter::aux::unaryfunptr_arg_type<Result>
{
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
typedef typename ::boost::parameter::aux::unaryfunptr_arg_type<Result>::type type;
# endif
};
#define BOOST_CONCEPT_REQUIRES_(r,data,t) + (::boost::_requires_<void(*)t>::value)
#if defined(NDEBUG) || BOOST_WORKAROUND(BOOST_MSVC, < 1300)
# define BOOST_CONCEPT_WHERE(models, result) \
# define BOOST_CONCEPT_REQUIRES(models, result) \
typename ::boost::parameter::aux::unaryfunptr_arg_type<void(*)result>::type
#elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
// Same thing as below without the initial typename
# define BOOST_CONCEPT_WHERE(models, result) \
BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_OPEN, ~, models) \
# define BOOST_CONCEPT_REQUIRES(models, result) \
::boost::Requires_< \
(0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \
::boost::parameter::aux::unaryfunptr_arg_type<void(*)result> \
BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_CLOSE, ~, models)::type
>::type
#else
// This just ICEs on MSVC6 :(
# define BOOST_CONCEPT_WHERE(models, result) \
typename BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_OPEN, ~, models) \
::boost::parameter::aux::unaryfunptr_arg_type<void(*)result> \
BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_CLOSE, ~, models)::type
# define BOOST_CONCEPT_REQUIRES(models, result) \
typename ::boost::Requires_< \
(0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \
void(*)result \
>::type
#endif
// C++0x proposed syntax changed. This supports an older usage
#define BOOST_CONCEPT_WHERE(models,result) BOOST_CONCEPT_REQUIRES(models,result)
} // namespace boost::concept_check
#endif // BOOST_CONCEPT_WHERE_DWA2006430_HPP
#endif // BOOST_CONCEPT_REQUIRES_DWA2006430_HPP

View File

@ -62,9 +62,6 @@ namespace boost
//
BOOST_concept(Integer, (T))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Integer(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(Integer)
{
x.error_type_must_be_an_integer_type();
@ -90,9 +87,6 @@ namespace boost
# endif
BOOST_concept(SignedInteger,(T)) {
#if BOOST_WORKAROUND(__GNUC__, <= 3)
SignedInteger(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(SignedInteger) {
x.error_type_must_be_a_signed_integer_type();
}
@ -110,9 +104,6 @@ namespace boost
# endif
BOOST_concept(UnsignedInteger,(T)) {
#if BOOST_WORKAROUND(__GNUC__, <= 3)
UnsignedInteger(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(UnsignedInteger) {
x.error_type_must_be_an_unsigned_integer_type();
}
@ -135,9 +126,6 @@ namespace boost
BOOST_concept(DefaultConstructible,(TT))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
DefaultConstructible(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(DefaultConstructible) {
TT a; // require default constructor
ignore_unused_variable_warning(a);
@ -146,13 +134,9 @@ namespace boost
BOOST_concept(Assignable,(TT))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Assignable(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(Assignable) {
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
a = a; // require assignment operator
a = a; // require assignment operator
#endif
const_constraints(a);
}
@ -166,12 +150,9 @@ namespace boost
TT a;
};
BOOST_concept(CopyConstructible,(TT))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
CopyConstructible(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(CopyConstructible) {
TT a(b); // require copy constructor
TT* ptr = &a; // require address of operator
@ -191,10 +172,6 @@ namespace boost
// The SGI STL version of Assignable requires copy constructor and operator=
BOOST_concept(SGIAssignable,(TT))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
SGIAssignable(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(SGIAssignable) {
TT b(a);
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
@ -216,9 +193,6 @@ namespace boost
BOOST_concept(Convertible,(X)(Y))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Convertible(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(Convertible) {
Y y = x;
ignore_unused_variable_warning(y);
@ -244,9 +218,6 @@ namespace boost
BOOST_concept(EqualityComparable,(TT))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
EqualityComparable(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(EqualityComparable) {
require_boolean_expr(a == b);
require_boolean_expr(a != b);
@ -257,9 +228,6 @@ namespace boost
BOOST_concept(LessThanComparable,(TT))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
LessThanComparable(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(LessThanComparable) {
require_boolean_expr(a < b);
}
@ -270,9 +238,6 @@ namespace boost
// This is equivalent to SGI STL's LessThanComparable.
BOOST_concept(Comparable,(TT))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Comparable(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(Comparable) {
require_boolean_expr(a < b);
require_boolean_expr(a > b);
@ -283,18 +248,6 @@ namespace boost
TT a, b;
};
#if BOOST_WORKAROUND(__GNUC__, <= 3)
#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
BOOST_concept(NAME, (First)(Second)) \
{ \
NAME(); \
BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \
private: \
bool constraints_() { return a OP b; } \
First a; \
Second b; \
}
#else
#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
BOOST_concept(NAME, (First)(Second)) \
{ \
@ -304,20 +257,7 @@ namespace boost
First a; \
Second b; \
}
#endif
#if BOOST_WORKAROUND(__GNUC__, <= 3)
#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \
BOOST_concept(NAME, (Ret)(First)(Second)) \
{ \
NAME(); \
BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \
private: \
Ret constraints_() { return a OP b; } \
First a; \
Second b; \
}
#else
#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \
BOOST_concept(NAME, (Ret)(First)(Second)) \
{ \
@ -327,7 +267,6 @@ namespace boost
First a; \
Second b; \
}
#endif
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp);
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp);
@ -347,9 +286,6 @@ namespace boost
BOOST_concept(Generator,(Func)(Return))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Generator(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(Generator) { test(is_void<Return>()); }
private:
@ -370,9 +306,6 @@ namespace boost
BOOST_concept(UnaryFunction,(Func)(Return)(Arg))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
UnaryFunction(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void<Return>()); }
private:
@ -394,9 +327,6 @@ namespace boost
BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
BinaryFunction(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void<Return>()); }
private:
void test(boost::mpl::false_)
@ -418,9 +348,6 @@ namespace boost
BOOST_concept(UnaryPredicate,(Func)(Arg))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
UnaryPredicate(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(UnaryPredicate) {
require_boolean_expr(f(arg)); // require operator() returning bool
}
@ -431,9 +358,6 @@ namespace boost
BOOST_concept(BinaryPredicate,(Func)(First)(Second))
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(BinaryPredicate) {
require_boolean_expr(f(a, b)); // require operator() returning bool
}
@ -447,9 +371,6 @@ namespace boost
BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second))
: BinaryPredicate<Func, First, Second>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Const_BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(Const_BinaryPredicate) {
const_constraints(f);
}
@ -468,9 +389,6 @@ namespace boost
{
typedef typename Func::result_type result_type;
#if BOOST_WORKAROUND(__GNUC__, <= 3)
AdaptableGenerator(); // at least 2.96 and 3.4.3 both need this :(
#endif
BOOST_CONCEPT_USAGE(AdaptableGenerator)
{
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
@ -483,9 +401,6 @@ namespace boost
typedef typename Func::argument_type argument_type;
typedef typename Func::result_type result_type;
#if BOOST_WORKAROUND(__GNUC__, <= 3)
AdaptableUnaryFunction(); // at least 2.96 and 3.4.3 both need this :(
#endif
~AdaptableUnaryFunction()
{
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
@ -505,9 +420,6 @@ namespace boost
typedef typename Func::second_argument_type second_argument_type;
typedef typename Func::result_type result_type;
#if BOOST_WORKAROUND(__GNUC__, <= 3)
AdaptableBinaryFunction(); // at least 2.96 and 3.4.3 both need this :(
#endif
~AdaptableBinaryFunction()
{
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
@ -520,18 +432,12 @@ namespace boost
: UnaryPredicate<Func, Arg>
, AdaptableUnaryFunction<Func, bool, Arg>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
AdaptablePredicate(); // at least 2.96 and 3.4.3 both need this :(
#endif
};
BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second))
: BinaryPredicate<Func, First, Second>
, AdaptableBinaryFunction<Func, bool, First, Second>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
AdaptableBinaryPredicate(); // at least 2.96 and 3.4.3 both need this :(
#endif
};
//===========================================================================
@ -547,10 +453,7 @@ namespace boost
typedef typename boost::detail::iterator_traits<TT>::pointer pointer;
typedef typename boost::detail::iterator_traits<TT>::iterator_category iterator_category;
#if BOOST_WORKAROUND(__GNUC__, <= 3)
InputIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~InputIterator()
BOOST_CONCEPT_USAGE(InputIterator)
{
BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>));
BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));
@ -567,10 +470,7 @@ namespace boost
BOOST_concept(OutputIterator,(TT)(ValueT))
: Assignable<TT>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
OutputIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~OutputIterator() {
BOOST_CONCEPT_USAGE(OutputIterator) {
++i; // require preincrement operator
i++; // require postincrement operator
@ -584,10 +484,7 @@ namespace boost
BOOST_concept(ForwardIterator,(TT))
: InputIterator<TT>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
ForwardIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~ForwardIterator()
BOOST_CONCEPT_USAGE(ForwardIterator)
{
BOOST_CONCEPT_ASSERT((Convertible<
BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category
@ -605,10 +502,7 @@ namespace boost
BOOST_concept(Mutable_ForwardIterator,(TT))
: ForwardIterator<TT>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Mutable_ForwardIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_ForwardIterator() {
BOOST_CONCEPT_USAGE(Mutable_ForwardIterator) {
*i++ = *i; // require postincrement and assignment
}
private:
@ -618,10 +512,7 @@ namespace boost
BOOST_concept(BidirectionalIterator,(TT))
: ForwardIterator<TT>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
BidirectionalIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~BidirectionalIterator()
BOOST_CONCEPT_USAGE(BidirectionalIterator)
{
BOOST_CONCEPT_ASSERT((Convertible<
BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category
@ -639,10 +530,7 @@ namespace boost
: BidirectionalIterator<TT>
, Mutable_ForwardIterator<TT>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Mutable_BidirectionalIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_BidirectionalIterator()
BOOST_CONCEPT_USAGE(Mutable_BidirectionalIterator)
{
*i-- = *i; // require postdecrement and assignment
}
@ -654,10 +542,7 @@ namespace boost
: BidirectionalIterator<TT>
, Comparable<TT>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
RandomAccessIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~RandomAccessIterator()
BOOST_CONCEPT_USAGE(RandomAccessIterator)
{
BOOST_CONCEPT_ASSERT((Convertible<
BOOST_DEDUCED_TYPENAME BidirectionalIterator<TT>::iterator_category
@ -682,10 +567,7 @@ namespace boost
: RandomAccessIterator<TT>
, Mutable_BidirectionalIterator<TT>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Mutable_RandomAccessIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_RandomAccessIterator()
BOOST_CONCEPT_USAGE(Mutable_RandomAccessIterator)
{
i[n] = *i; // require element access and assignment
}
@ -707,10 +589,7 @@ namespace boost
typedef typename C::const_pointer const_pointer;
typedef typename C::const_iterator const_iterator;
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Container(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Container()
BOOST_CONCEPT_USAGE(Container)
{
BOOST_CONCEPT_ASSERT((InputIterator<const_iterator>));
const_constraints(c);
@ -737,10 +616,7 @@ namespace boost
typedef typename C::iterator iterator;
typedef typename C::pointer pointer;
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Mutable_Container(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_Container()
BOOST_CONCEPT_USAGE(Mutable_Container)
{
BOOST_CONCEPT_ASSERT((
Assignable<typename Mutable_Container::value_type>));
@ -760,10 +636,7 @@ namespace boost
BOOST_concept(ForwardContainer,(C))
: Container<C>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
ForwardContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~ForwardContainer()
BOOST_CONCEPT_USAGE(ForwardContainer)
{
BOOST_CONCEPT_ASSERT((
ForwardIterator<
@ -776,10 +649,7 @@ namespace boost
: ForwardContainer<C>
, Mutable_Container<C>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Mutable_ForwardContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_ForwardContainer()
BOOST_CONCEPT_USAGE(Mutable_ForwardContainer)
{
BOOST_CONCEPT_ASSERT((
Mutable_ForwardIterator<
@ -795,10 +665,7 @@ namespace boost
C::const_reverse_iterator
const_reverse_iterator;
#if BOOST_WORKAROUND(__GNUC__, <= 3)
ReversibleContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~ReversibleContainer()
BOOST_CONCEPT_USAGE(ReversibleContainer)
{
BOOST_CONCEPT_ASSERT((
BidirectionalIterator<
@ -823,10 +690,7 @@ namespace boost
{
typedef typename C::reverse_iterator reverse_iterator;
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Mutable_ReversibleContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_ReversibleContainer()
BOOST_CONCEPT_USAGE(Mutable_ReversibleContainer)
{
typedef typename Mutable_ForwardContainer<C>::iterator iterator;
BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<iterator>));
@ -845,10 +709,7 @@ namespace boost
typedef typename C::size_type size_type;
typedef typename C::const_reference const_reference;
#if BOOST_WORKAROUND(__GNUC__, <= 3)
RandomAccessContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~RandomAccessContainer()
BOOST_CONCEPT_USAGE(RandomAccessContainer)
{
BOOST_CONCEPT_ASSERT((
RandomAccessIterator<
@ -875,10 +736,7 @@ namespace boost
private:
typedef Mutable_RandomAccessContainer self;
public:
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Mutable_RandomAccessContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_RandomAccessContainer()
BOOST_CONCEPT_USAGE(Mutable_RandomAccessContainer)
{
BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::iterator>));
BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::reverse_iterator>));
@ -900,10 +758,7 @@ namespace boost
// ... so why aren't we following the standard? --DWA
, DefaultConstructible<S>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
Sequence(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Sequence()
BOOST_CONCEPT_USAGE(Sequence)
{
S
c(n),
@ -940,10 +795,7 @@ namespace boost
BOOST_concept(FrontInsertionSequence,(S))
: Sequence<S>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
FrontInsertionSequence(); // at least 2.96 and 3.4.3 both need this :(
#endif
~FrontInsertionSequence()
BOOST_CONCEPT_USAGE(FrontInsertionSequence)
{
c.push_front(t);
c.pop_front();
@ -956,10 +808,7 @@ namespace boost
BOOST_concept(BackInsertionSequence,(S))
: Sequence<S>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
BackInsertionSequence(); // at least 2.96 and 3.4.3 both need this :(
#endif
~BackInsertionSequence()
BOOST_CONCEPT_USAGE(BackInsertionSequence)
{
c.push_back(t);
c.pop_back();
@ -986,10 +835,7 @@ namespace boost
typedef typename C::value_compare value_compare;
typedef typename C::iterator iterator;
#if BOOST_WORKAROUND(__GNUC__, <= 3)
AssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~AssociativeContainer()
BOOST_CONCEPT_USAGE(AssociativeContainer)
{
i = c.find(k);
r = c.equal_range(k);
@ -1025,10 +871,7 @@ namespace boost
BOOST_concept(UniqueAssociativeContainer,(C))
: AssociativeContainer<C>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
UniqueAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~UniqueAssociativeContainer()
BOOST_CONCEPT_USAGE(UniqueAssociativeContainer)
{
C c(first, last);
@ -1046,10 +889,7 @@ namespace boost
BOOST_concept(MultipleAssociativeContainer,(C))
: AssociativeContainer<C>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
MultipleAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~MultipleAssociativeContainer()
BOOST_CONCEPT_USAGE(MultipleAssociativeContainer)
{
C c(first, last);
@ -1068,10 +908,7 @@ namespace boost
BOOST_concept(SimpleAssociativeContainer,(C))
: AssociativeContainer<C>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
SimpleAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~SimpleAssociativeContainer()
BOOST_CONCEPT_USAGE(SimpleAssociativeContainer)
{
typedef typename C::key_type key_type;
typedef typename C::value_type value_type;
@ -1082,10 +919,7 @@ namespace boost
BOOST_concept(PairAssociativeContainer,(C))
: AssociativeContainer<C>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
PairAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~PairAssociativeContainer()
BOOST_CONCEPT_USAGE(PairAssociativeContainer)
{
typedef typename C::key_type key_type;
typedef typename C::value_type value_type;
@ -1099,10 +933,7 @@ namespace boost
: AssociativeContainer<C>
, ReversibleContainer<C>
{
#if BOOST_WORKAROUND(__GNUC__, <= 3)
SortedAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~SortedAssociativeContainer()
BOOST_CONCEPT_USAGE(SortedAssociativeContainer)
{
C
c(kc),

View File

@ -1,57 +1,55 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 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>Programming With Concepts</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../boost.png"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<h2><a name="programming-with-concepts">Programming with Concepts</a></h2>
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
The process of deciding how to group requirements into concepts and
deciding which concepts to use in each algorithm is perhaps the most
difficult (yet most important) part of building a generic library.
A guiding principle to use during this process is one we
call the <i>requirement minimization principle</i>.
<title>Programming With Concepts</title>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
<link rel="stylesheet" href="../../rst.css" type="text/css" />
</head>
<p>
<b>Requirement Minimization Principle:</b> Minimize the requirements
on the input parameters of a component to increase its reusability.
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<p>
There is natural tension in this statement. By definition, the input
parameters must be used by the component in order for the component to
accomplish its task (by ``component'' we mean a function or class
template). The challenge then is to implement the component in such a
way that makes the fewest assumptions (the minimum requirements) about
the inputs while still accomplishing the task.
<h2><a name="programming-with-concepts" id=
"programming-with-concepts">Programming with Concepts</a></h2>
<p>
The traditional notions of <i>abstraction</i> tie in directly to the
idea of minimal requirements. The more abstract the input, the fewer
the requirements. Thus, concepts are simply the embodiment of generic
abstract data types in C++ template programming.
<p>The process of deciding how to group requirements into concepts and
deciding which concepts to use in each algorithm is perhaps the most
difficult (yet most important) part of building a generic library. A
guiding principle to use during this process is one we call the
<i>requirement minimization principle</i>.</p>
<p>
When designing the concepts for some problem domain it is important to
keep in mind their purpose, namely to express the requirements for the
input to the components. With respect to the requirement minimization
principle, this means we want to minimize concepts.
<p><b>Requirement Minimization Principle:</b> Minimize the requirements on
the input parameters of a component to increase its reusability.</p>
<!-- the following discussion does not match the Standard definition
<p>There is natural tension in this statement. By definition, the input
parameters must be used by the component in order for the component to
accomplish its task (by ``component'' we mean a function or class
template). The challenge then is to implement the component in such a way
that makes the fewest assumptions (the minimum requirements) about the
inputs while still accomplishing the task.</p>
<p>The traditional notions of <i>abstraction</i> tie in directly to the
idea of minimal requirements. The more abstract the input, the fewer the
requirements. Thus, concepts are simply the embodiment of generic abstract
data types in C++ template programming.</p>
<p>When designing the concepts for some problem domain it is important to
keep in mind their purpose, namely to express the requirements for the
input to the components. With respect to the requirement minimization
principle, this means we want to minimize concepts.
<!-- the following discussion does not match the Standard definition
of LessThanComparable and needs to be changed -Jeremy
<p>
@ -88,7 +86,7 @@ principle because all of the comparison operators (<tt>&lt;</tt>,
<tt>></tt>, <tt><=</tt>, <tt>>=</tt>) are conceptually equivalent (in
a mathematical sense). Adding conceptually equivalent valid
expressions is not a violation of the requirement minimization
principle because no new semantics are being added --- only new
principle because no new semantics are being added === only new
syntax. The added syntax increases re-usability.
<p>
@ -105,44 +103,42 @@ LessThanComparable</a> is given as the requirement for
<tt>std::stable_sort()</tt>, then the maintainer is given a reasonable
amount of flexibility within which to work.
-->
--></p>
<p>
Minimality in concepts is a property associated with the underlying
semantics of the problem domain being represented. In the problem
domain of basic containers, requiring traversal in a single direction
is a smaller requirement than requiring traversal in both directions
(hence the distinction between <a
href="http://www.sgi.com/tech/stl/ForwardIterator.html">
ForwardIterator</a> and
<a
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">
BidirectionalIterator</a>). The semantic difference can be easily seen
in the difference between the set of concrete data structures that
have forward iterators versus the set that has bidirectional
iterators. For example, singly-linked lists would fall in the set of
data structures having forward iterators, but not bidirectional
iterators. In addition, the set of algorithms that one can implement
using only forward iterators is quite different than the set that can
be implemented with bidirectional iterators. Because of this, it is
important to factor families of requirements into rather fine-grained
concepts. For example, the requirements for iterators are factored
into the six STL iterator concepts (trivial, output, input, forward,
bidirectional, and random access).
<p>Minimality in concepts is a property associated with the underlying
semantics of the problem domain being represented. In the problem domain of
basic containers, requiring traversal in a single direction is a smaller
requirement than requiring traversal in both directions (hence the
distinction between <a href=
"http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a> and
<a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>).
The semantic difference can be easily seen in the difference between the
set of concrete data structures that have forward iterators versus the set
that has bidirectional iterators. For example, singly-linked lists would
fall in the set of data structures having forward iterators, but not
bidirectional iterators. In addition, the set of algorithms that one can
implement using only forward iterators is quite different than the set that
can be implemented with bidirectional iterators. Because of this, it is
important to factor families of requirements into rather fine-grained
concepts. For example, the requirements for iterators are factored into the
six STL iterator concepts (trivial, output, input, forward, bidirectional,
and random access).</p>
<p>
<a href="./implementation.htm">Next: Implementation</a><br>
<a href="./concept_covering.htm">Prev: Concept Covering and Archetypes</a>
<p><a href="./implementation.htm">Next: Implementation</a><br />
<a href="./concept_covering.htm">Prev: Concept Covering and
Archetypes</a><br /></p>
<hr />
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
</BODY>
</HTML>
<td><a href="../../people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>),
2007 <a href="mailto:dave@boost-consulting.com">David Abrahams</a>.
</tr>
</table>
</body>
</html>

View File

@ -1,308 +1,391 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 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>Boost Concept Checking Reference</Title>
</Head>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../boost.png"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<h2><a name="reference">Reference</a></h2>
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../../rst.css" type="text/css" />
<OL>
<LI><a href="#functions">Functions</a></LI>
<LI><a href="#macros">Macros</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="#function-object-concepts">Function Object Concept Checking Classes</a></LI>
<LI><a href="#container-concepts">Container Concept Checking Classes</a></LI>
<LI><a href="#basic-archetype">Basic Archetype Classes</a></LI>
<LI><a href="#iterator-archetype">Iterator Archetype Classes</a></LI>
<LI><a href="#function-object-archetype">Function Object Archetype Classes</a></LI>
<LI><a href="#container-archetype">Container Archetype Classes</a></LI>
</OL>
<title>Boost Concept Checking Reference</title>
</head>
<h3><a name="functions">Functions</a></h3>
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<pre>
template &lt;class Concept&gt;
void function_requires();
<h2><a name="reference" id="reference">Reference</a></h2>
<ol>
<li><a href="#macros">Macros</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="#function-object-concepts">Function Object Concept Checking
Classes</a></li>
<li><a href="#container-concepts">Container Concept Checking
Classes</a></li>
<li><a href="#basic-archetype">Basic Archetype Classes</a></li>
<li><a href="#iterator-archetype">Iterator Archetype Classes</a></li>
<li><a href="#function-object-archetype">Function Object Archetype
Classes</a></li>
<li><a href="#container-archetype">Container Archetype Classes</a></li>
<li><a href="#deprecated-functions">Deprecated Functions</a></li>
<li><a href="#deprecated-macros">Deprecated Macros</a></li>
<li><a href="#deprecated-concept-checking-classes">Deprecated Concept
Checking Classes</a></li>
</ol>
<h3><a name="macros" id="macros">Macros</a></h3>
<pre>
#include "boost/concept/assert.hpp"
BOOST_CONCEPT_ASSERT((<em>concept checking class template specialization</em>));
</pre>
<h3><a name="macros">Macros</a></h3>
<p><strong>Effects:</strong> causes a compilation failure if the concept is
not satisfied.<br />
<strong>Note:</strong> this macro can be used at global, class, or function
scope.</p>
<pre>
// Apply concept checks in class definitions.
BOOST_CLASS_REQUIRE(<i>type</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE2(<i>type1</i>, <i>type2</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>namespace-of-concept</i>, <i>concept</i>);
<h3><a name="basic-concepts" id="basic-concepts">Basic Concept Checking
Classes</a></h3>
<pre>
#include "boost/concept_check.hpp"
template &lt;class T&gt;
struct Integer; // Is T a built-in integer type?
template &lt;class T&gt;
struct SignedInteger; // Is T a built-in signed integer type?
template &lt;class T&gt;
struct UnsignedInteger; // Is T a built-in unsigned integer type?
template &lt;class X, class Y&gt;
struct Convertible; // Is X convertible to Y?
template &lt;class T&gt;
struct <a href=
"../utility/Assignable.html">Assignable</a>; // Standard ref 23.1
template &lt;class T&gt;
struct SGI<a href=
"http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>;
template &lt;class T&gt;
struct <a href=
"http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>;
template &lt;class T&gt;
struct <a href=
"../utility/CopyConstructible.html">CopyConstructible</a>; // Standard ref 20.1.3
template &lt;class T&gt;
struct <a href=
"http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>; // Standard ref 20.1.1
template &lt;class T&gt;
struct <a href=
"../utility/LessThanComparable.html">LessThanComparable</a>; // Standard ref 20.1.2
template &lt;class T&gt;
struct Comparable; // The SGI STL <a href=
"http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a> concept
</pre>
Deprecated macros:
<h3><a name="iterator-concepts" id="iterator-concepts">Iterator Concept
Checking Classes</a></h3>
<pre>
template &lt;class Iter&gt;
struct <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>; // Standard ref 24.1.1 Table 72
<pre>
// Apply concept checks in class definitions.
BOOST_CLASS_REQUIRES(<i>type</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES2(<i>type1</i>, <i>type2</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>);
template &lt;class Iter, class T&gt;
struct <a href=
"http://www.sgi.com/tech/stl/OutputIterator.html">OutputIterator</a>; // Standard ref 24.1.2 Table 73
template &lt;class Iter&gt;
struct <a href=
"http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>; // Standard ref 24.1.3 Table 74
template &lt;class Iter&gt;
struct Mutable_ForwardIterator;
template &lt;class Iter&gt;
struct <a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>; // Standard ref 24.1.4 Table 75
template &lt;class Iter&gt;
struct Mutable_BidirectionalIterator;
template &lt;class Iter&gt;
struct <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>; // Standard ref 24.1.5 Table 76
template &lt;class Iter&gt;
struct Mutable_RandomAccessIterator;
</pre>
<h3><a name="basic-concepts">Basic Concept Checking Classes</a></h3>
<h3><a name="function-object-concepts" id=
"function-object-concepts">Function Object Concept Checking
Classes</a></h3>
<pre>
#include "boost/concept_check.hpp"
<pre>
template &lt;class T&gt;
struct IntegerConcept; // Is T a built-in integer type?
template &lt;class Func, class Return&gt;
struct <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>;
template &lt;class T&gt;
struct SignedIntegerConcept; // Is T a built-in signed integer type?
template &lt;class Func, class Return, class Arg&gt;
struct <a href=
"http://www.sgi.com/tech/stl/UnaryFunction.html">UnaryFunction</a>;
template &lt;class T&gt;
struct UnsignedIntegerConcept; // Is T a built-in unsigned integer type?
template &lt;class Func, class Return, class First, class Second&gt;
struct <a href=
"http://www.sgi.com/tech/stl/BinaryFunction.html">BinaryFunction</a>;
template &lt;class X, class Y&gt;
struct ConvertibleConcept; // Is X convertible to Y?
template &lt;class Func, class Arg&gt;
struct Unary<a href=
"http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>;
template &lt;class T&gt;
struct <a href="../utility/Assignable.html">Assignable</a>Concept; // Standard ref 23.1
template &lt;class Func, class First, class Second&gt;
struct <a href=
"http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>;
template &lt;class T&gt;
struct SGI<a href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>Concept;
template &lt;class Func, class First, class Second&gt;
struct Const_BinaryPredicate;
template &lt;class T&gt;
struct <a
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>Concept;
template &lt;class Func, class Return&gt;
struct <a href=
"http://www.sgi.com/tech/stl/AdaptableGenerator.html">AdaptableGenerator</a>;
template &lt;class T&gt;
struct <a href="../utility/CopyConstructible.html">CopyConstructible</a>Concept; // Standard ref 20.1.3
template &lt;class Func, class Return, class Arg&gt;
struct <a href=
"http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>;
template &lt;class T&gt;
struct <a href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>Concept; // Standard ref 20.1.1
template &lt;class Func, class First, class Second&gt;
struct <a href=
"http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>;
template &lt;class T&gt;
struct <a href="../utility/LessThanComparable.html">LessThanComparable</a>Concept; // Standard ref 20.1.2
template &lt;class Func, class Arg&gt;
struct <a href=
"http://www.sgi.com/tech/stl/AdaptablePredicate.html">AdaptablePredicate</a>;
template &lt;class T&gt;
struct ComparableConcept; // The SGI STL <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a> concept
template &lt;class Func, class First, class Second&gt;
struct <a href=
"http://www.sgi.com/tech/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>;
</pre>
<h3><a name="iterator-concepts">Iterator Concept Checking Classes</a></h3>
<h3><a name="container-concepts" id="container-concepts">Container Concept
Checking Classes</a></h3>
<pre>
#include "boost/concept_check.hpp"
<pre>
template &lt;class Iter&gt;
struct <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>Concept; // Standard ref 24.1.1 Table 72
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/Container.html">Container</a>; // Standard ref 23.1 Table 65
template &lt;class Iter, class T&gt;
struct <a href="http://www.sgi.com/tech/stl/OutputIterator.html">OutputIterator</a>Concept; // Standard ref 24.1.2 Table 73
template &lt;class C&gt;
struct Mutable_Container;
template &lt;class Iter&gt;
struct <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>Concept; // Standard ref 24.1.3 Table 74
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/ForwardContainer.html">ForwardContainer</a>;
template &lt;class Iter&gt;
struct Mutable_ForwardIteratorConcept;
template &lt;class C&gt;
struct Mutable_ForwardContainer;
template &lt;class Iter&gt;
struct <a href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>Concept; // Standard ref 24.1.4 Table 75
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/ReversibleContainer.html">ReversibleContainer</a>; // Standard ref 23.1 Table 66
template &lt;class Iter&gt;
struct Mutable_BidirectionalIteratorConcept;
template &lt;class C&gt;
struct Mutable_ReversibleContainer;
template &lt;class Iter&gt;
struct <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>Concept; // Standard ref 24.1.5 Table 76
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/RandomAccessContainer.html">RandomAccessContainer</a>;
template &lt;class Iter&gt;
struct Mutable_RandomAccessIteratorConcept;
template &lt;class C&gt;
struct Mutable_RandomAccessContainer;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/Sequence.html">Sequence</a>; // Standard ref 23.1.1
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/BackInsertionSequence.html">BackInsertionSequence</a>;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/AssociativeContainer.html">AssociativeContainer</a>; // Standard ref 23.1.2 Table 69
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>;
</pre>
<h3><a name="function-object-concepts">Function Object Concept Checking Classes</a></h3>
<h3><a name="basic-archetype" id="basic-archetype">Basic Archetype
Classes</a></h3>
<pre>
#include "boost/concept_archetype.hpp"
<pre>
template &lt;class Func, class Return&gt;
struct <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>Concept;
template &lt;class T = int&gt;
class null_archetype; // A type that models no concepts.
template &lt;class Func, class Return, class Arg&gt;
struct <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">UnaryFunction</a>Concept;
template &lt;class Base = null_archetype&gt;
class default_constructible_archetype;
template &lt;class Func, class Return, class First, class Second&gt;
struct <a href="http://www.sgi.com/tech/stl/BinaryFunction.html">BinaryFunction</a>Concept;
template &lt;class Base = null_archetype&gt;
class assignable_archetype;
template &lt;class Func, class Arg&gt;
struct Unary<a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>Concept;
template &lt;class Base = null_archetype&gt;
class copy_constructible_archetype;
template &lt;class Func, class First, class Second&gt;
struct <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>Concept;
template &lt;class Base = null_archetype&gt;
class equality_comparable_archetype;
template &lt;class Func, class First, class Second&gt;
struct Const_BinaryPredicateConcept;
template &lt;class Func, class Return&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableGenerator.html">AdaptableGenerator</a>Concept;
template &lt;class Func, class Return, class Arg&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>Concept;
template &lt;class Func, class First, class Second&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>Concept;
template &lt;class Func, class Arg&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptablePredicate.html">AdaptablePredicate</a>Concept;
template &lt;class Func, class First, class Second&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>Concept;
template &lt;class T, class Base = null_archetype&gt;
class convertible_to_archetype;
</pre>
<h3><a name="container-concepts">Container Concept Checking Classes</a></h3>
<h3><a name="iterator-archetype" id="iterator-archetype">Iterator Archetype
Classes</a></h3>
<pre>
#include "boost/concept_archetype.hpp"
<pre>
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>Concept; // Standard ref 23.1 Table 65
template &lt;class ValueType&gt;
class trivial_iterator_archetype;
template &lt;class C&gt;
struct Mutable_ContainerConcept;
template &lt;class ValueType&gt;
class mutable_trivial_iterator_archetype;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/ForwardContainer.html">ForwardContainer</a>Concept;
template &lt;class ValueType&gt;
class input_iterator_archetype;
template &lt;class C&gt;
struct Mutable_ForwardContainerConcept;
template &lt;class ValueType&gt;
class forward_iterator_archetype;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/ReversibleContainer.html">ReversibleContainer</a>Concept; // Standard ref 23.1 Table 66
template &lt;class ValueType&gt;
class bidirectional_iterator_archetype;
template &lt;class C&gt;
struct Mutable_ReversibleContainerConcept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/RandomAccessContainer.html">RandomAccessContainer</a>Concept;
template &lt;class C&gt;
struct Mutable_RandomAccessContainerConcept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/Sequence.html">Sequence</a>Concept; // Standard ref 23.1.1
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/BackInsertionSequence.html">BackInsertionSequence</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/AssociativeContainer.html">AssociativeContainer</a>Concept; // Standard ref 23.1.2 Table 69
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>Concept;
template &lt;class ValueType&gt;
class random_access_iterator_archetype;
</pre>
<h3><a name="function-object-archetype" id=
"function-object-archetype">Function Object Archetype Classes</a></h3>
<pre>
#include "boost/concept_archetype.hpp"
<h3><a name="basic-archetype">Basic Archetype Classes</a></h3>
template &lt;class Arg, class Return&gt;
class unary_function_archetype;
<pre>
template &lt;class T = int&gt;
class null_archetype; // A type that models no concepts.
template &lt;class Arg1, class Arg2, class Return&gt;
class binary_function_archetype;
template &lt;class Base = null_archetype&gt;
class default_constructible_archetype;
template &lt;class Arg&gt;
class predicate_archetype;
template &lt;class Base = null_archetype&gt;
class assignable_archetype;
template &lt;class Base = null_archetype&gt;
class copy_constructible_archetype;
template &lt;class Base = null_archetype&gt;
class equality_comparable_archetype;
template &lt;class T, class Base = null_archetype&gt;
class convertible_to_archetype;
template &lt;class Arg1, class Arg2&gt;
class binary_predicate_archetype;
</pre>
<h3><a name="iterator-archetype">Iterator Archetype Classes</a></h3>
<pre>
template &lt;class ValueType&gt;
class trivial_iterator_archetype;
template &lt;class ValueType&gt;
class mutable_trivial_iterator_archetype;
template &lt;class ValueType&gt;
class input_iterator_archetype;
template &lt;class ValueType&gt;
class forward_iterator_archetype;
template &lt;class ValueType&gt;
class bidirectional_iterator_archetype;
template &lt;class ValueType&gt;
class random_access_iterator_archetype;
</pre>
<h3><a name="function-object-archetype">Function Object Archetype Classes</a></h3>
<pre>
template &lt;class Arg, class Return&gt;
class unary_function_archetype;
template &lt;class Arg1, class Arg2, class Return&gt;
class binary_function_archetype;
template &lt;class Arg&gt;
class predicate_archetype;
template &lt;class Arg1, class Arg2&gt;
class binary_predicate_archetype;
</pre>
<h3><a name="container-archetype">Container Archetype Classes</a></h3>
<pre>
<h3><a name="container-archetype" id="container-archetype">Container
Archetype Classes</a></h3>
<pre>
UNDER CONSTRUCTION
</pre>
<p>
<a href="./concept_check.htm">Back to Introduction</a>
<br>
<a href="./implementation.htm">Prev: Implementation</a>
<h3><a name="deprecated-functions" id="deprecated-functions">Deprecated
Functions</a></h3>
<pre>
#include "boost/concept_check.hpp"
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
template &lt;class Concept&gt;
void function_requires();
</pre>
</BODY>
</HTML>
<h3><a name="deprecated-macros" id="deprecated-macros">Deprecated
Macros</a></h3>
<pre>
#include "boost/concept_check.hpp"
// Apply concept checks in class definitions.
BOOST_CLASS_REQUIRE(<i>type</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE2(<i>type1</i>, <i>type2</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>namespace-of-concept</i>, <i>concept</i>);
BOOST_CLASS_REQUIRE4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>namespace-of-concept</i>, <i>concept</i>);
// Apply concept checks in class definitions.
BOOST_CLASS_REQUIRES(<i>type</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES2(<i>type1</i>, <i>type2</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>);
</pre>
<h3><a name="deprecated-concept-checking-classes" id=
"deprecated-concept-checking-classes">Deprecated Concept Checking
Classes</a></h3>
<p>For each of the concepts documented here, the library includes an
identical concept checking class whose name ends in
<code>Concept</code>” For example, in
addition to <code>RandomAccessIterator</code>, the library defines a
<code>RandomAccessIteratorConcept</code> class template.</p>
<p><a href="./concept_check.htm">Back to Introduction</a><br />
<a href="./implementation.htm">Prev: Implementation</a><br /></p>
<hr />
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
<td><a href="../../people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>), 2007
<a href="mailto:dave@boost-consulting.com">David Abrahams</a>.</td>
</tr>
</table>
</body>
</html>

View File

@ -1,227 +1,186 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek 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>Using Concept Checks</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../boost.png"
ALT="C++ Boost" width="277" height="86">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<BR Clear>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000 -->
<!-- Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<head>
<meta name="generator" content=
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
<h2><a name="using-concept-checks">Using Concept Checks</a></h2>
<title>Using Concept Checks</title>
<link rel="stylesheet" href="../../rst.css" type="text/css" />
</head>
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 (BCCL) includes concept checking classes
for all of the concepts used in the C++ standard library and a few
more. The <a href="./reference.htm">Reference</a> section lists these
concept checking classes. In addition, other boost libraries come with
concept checking classes for the concepts that are particular to those
libraries. For example, there are <a
href="../graph/doc/graph_concepts.html">graph concepts</a> and <a
href="../property_map/property_map.html">property map concepts</a>.
Also, whenever <b>anyone</b> writing a class of function template
needs to express requirements that are not yet stated by an existing
concept, a new concept checking class should be created. How
to do this is explained in <a href="./creating_concepts.htm">Creating
Concept Checking Classes</a>.
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<p>
An example of a concept checking class from the BCCL is the
<tt>EqualityComparableConcept</tt> class. The class corresponds to the
EqualityComparable requirements described in 20.1.1 of the C++
Standard, and to the <a
href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>
concept documented in the SGI STL.
<h2><a name="using-concept-checks" id="using-concept-checks">Using Concept
Checks</a></h2>
<pre>
template &lt;class T&gt;
struct EqualityComparableConcept;
<p>For each concept there is a concept checking class template that can be
used to make sure that a given type (or set of types) models the concept.
The Boost Concept Checking Library (BCCL) includes concept checking class
templates for all of the concepts used in the C++ standard library and a
few more. See the <a href="./reference.htm">Reference</a> section for a
complete list. In addition, other boost libraries come with concept
checking classes for the concepts that are particular to those libraries.
For example, there are <a href="../graph/doc/graph_concepts.html">graph
concepts</a> and <a href="../property_map/property_map.html">property map
concepts</a>. Also, whenever <b>anyone</b> writing function templates needs
to express requirements that are not yet stated by an existing concept, a
new concept checking class should be created. How to do this is explained
in <a href="./creating_concepts.htm">Creating Concept Checking
Classes</a>.</p>
<p>An example of a concept checking class from the BCCL is the
<tt>EqualityComparableConcept</tt> class. The class corresponds to the
EqualityComparable requirements described in 20.1.1 of the C++ Standard,
and to the <a href=
"http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>
concept documented in the SGI STL.</p>
<pre>
template &lt;class T&gt;
struct EqualityComparable;
</pre>
The template argument <tt>T</tt> will the type to be checked. That is,
the purpose of <tt>EqualityComparableConcept</tt> is to make sure that
the template argument given for <tt>T</tt> models the
EqualityComparable concept.
<p>The template argument is the type to be checked. That is, the purpose of
<tt>EqualityComparable&lt;<em>X</em>&gt;</tt> is to make sure that
<tt><em>X</em></tt> models the EqualityComparable concept.</p>
<p>
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 is EqualityComparable we need to
instantiate the concept checking class with the type and then find a
way to get the compiler to compile the <tt>constraints()</tt> function
without actually executing the function. The Boost Concept Checking
Library defines two utilities that make this easy:
<tt>function_requires()</tt> and <tt>BOOST_CLASS_REQUIRE</tt>.
<h4><tt>BOOST_CONCEPT_ASSERT()</tt></h4>
<h4><tt>function_requires()</tt></h4>
<p>The most versatile way of checking concept requirements is to use the
<code>BOOST_CONCEPT_ASSERT()</code> macro. You can use this macro at any
scope, by passing a concept checking template specialization enclosed in
parentheses. <strong>Note:</strong> that means invocations of
<code>BOOST_CONCEPT_ASSERT</code> will appear to use <strong>double
parentheses</strong>.</p>
<pre>
<font color="green">// In my library:</font>
template &lt;class T&gt;
void generic_library_function(T x)
{
BOOST_CONCEPT_ASSERT<strong>((</strong>EqualityComparable&lt;T&gt;<strong>))</strong>;
<font color="green">// ...</font>
};
The <tt>function_requires()</tt> function can be used in function bodies
and the <tt>BOOST_CLASS_REQUIRE</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.
template &lt;class It&gt;
class generic_library_class
{
BOOST_CONCEPT_ASSERT<strong>((</strong>RandomAccessIterator&lt;It&gt;<strong>))</strong>;
<font color="green">// ...</font>
};
<pre>
// In my library:
template &lt;class T&gt;
void generic_library_function(T x)
{
function_requires&lt; EqualityComparableConcept&lt;T&gt; &gt;();
// ...
};
<font color="green">// In the user's code:</font>
class foo {
<font color="green">//... </font>
};
// In the user's code:
class foo {
//...
};
int main() {
foo f;
generic_library_function(f);
return 0;
}
int main() {
foo x;
generic_library_function(x);
generic_library_class&lt;std::vector&lt;char&gt;::iterator&gt; y;
<font color="green">//...</font>
}
</pre>
<h4><tt>BOOST_CONCEPT_REQUIRES</tt></h4>
<h4><tt>BOOST_CLASS_REQUIRE</tt></h4>
<p>One of the nice things about the proposed C++0x <a href=
"http://www.generic-programming.org/languages/conceptcpp/tutorial">syntax
for declaring concept constrained function templates</a> is the way that
constraints are part of the function <em>declaration</em>, so clients will
see them. <code>BOOST_CONCEPT_ASSERT</code> can only express constraints
within the function template definition, which hides the constraint in the
function body. Aside from the loss of a self-documenting interface,
asserting conformance only in the function body can undesirably delay
checking if the function is explicitly instantiated in a different
translation unit from the one in which it is called, or if the compiler
does link-time instantiation.</p>
The <tt>BOOST_CLASS_REQUIRE</tt> macro can be used inside a class
definition to check whether some type models a concept. Make sure
that the arguments to this macro are simply identifiers. You may need
to use typedef to get your types into this form.
<pre>
// In my library:
template &lt;class T&gt;
struct generic_library_class
{
BOOST_CLASS_REQUIRE(T, boost, EqualityComparableConcept);
// ...
};
// In the user's code:
class foo {
//...
};
int main() {
generic_library_class&lt;foo&gt; glc;
// ...
return 0;
}
<p>The <tt>BOOST_CONCEPT_REQUIRES</tt> macro can be used in a function
template declaration to check whether some type models a concept. It
accepts two arguments, a <strong>list of constraints</strong>, and the
function template's return type. The list of constraints takes the form of
a sequence of adjacent concept checking template specializations,
<strong>in double parentheses</strong>, and the function's return type must
also be parenthesized. For example, the standard <code>stable_sort</code>
algorithm might be declared as follows: class</p>
<pre>
template&lt;typename RanIter&gt;
BOOST_CONCEPT_REQUIRES(
((Mutable_RandomAccessIterator&lt;RanIter&gt;))
((LessThanComparable&lt;typename Mutable_RandomAccessIterator&lt;RanIter&gt;::value_type&gt;)),
(void)) <font color="green">// return type</font>
stable_sort(RanIter,RanIter);
</pre>
<p>Note that the algorithm requires that the value type of the iterator be
LessThanComparable, and it accesses that value type through the
<code>Mutable_RandomAccessIterator</code> concept checking template. In
general, the Boost concept checking classes expose associated types as
nested member typedefs so that you can use this syntax, which mimics the
approach used in the concept support proposed for the next version of
C++.</p>
<h4>Example</h4>
<h4>Multi-Type Concepts</h4>
<p>
Getting back to the earlier <a
href="./concept_check.htm#motivating-example">motivating example</a>,
one good application of concept checks would be to 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/tech/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/tech/stl/LessThanComparable.html">
LessThanComparable</a>, so we also use <tt>function_requires()</tt> to
check this.
<pre>
template &lt;class RandomAccessIter&gt;
void stable_sort(RandomAccessIter first, RandomAccessIter last)
{
function_requires&lt; RandomAccessIteratorConcept&lt;RandomAccessIter&gt; &gt;();
typedef typename std::iterator_traits&lt;RandomAccessIter&gt;::value_type value_type;
function_requires&lt; LessThanComparableConcept&lt;value_type&gt; &gt;();
...
}
<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>BOOST_CONCEPT_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.</p>
<pre>
template &lt;class G, class Buffer, class BFSVisitor,
class ColorMap&gt;
BOOST_CONCEPT_REQUIRES(
((ReadWritePropertyMap&lt;ColorMap, typename IncidenceGraph&lt;G&gt;::vertex_descriptor&gt;)),
(void)) <font color="green">// return type</font>
breadth_first_search(G&amp; g,
typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor s,
Buffer&amp; Q, BFSVisitor vis, ColorMap color)
{
typedef typename IncidenceGraph&lt;G&gt;::vertex_descriptor Vertex;
...
}
</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 &lt;class IncidenceGraph, class Buffer, class BFSVisitor,
class ColorMap&gt;
void breadth_first_search(IncidenceGraph& g,
typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor s,
Buffer& Q, BFSVisitor vis, ColorMap color)
{
typedef typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor Vertex;
function_requires&lt; ReadWritePropertyMap&lt;ColorMap, Vertex&gt; &gt;();
...
}
<p>Although 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. The syntactic
requirements, at least, can easily be checked by creating a small program
and using <tt>BOOST_CONCEPT_ASSERT</tt> with the type and concept in
question. For example:</p>
<pre>
<font color=
"green">// Make sure list&lt;int&gt; has bidirectional iterators.</font>
BOOST_CONCEPT_ASSERT((BidirectionalIterator&lt;std::list&lt;int&gt;::iterator&gt;));
</pre>
<p><a href="./concept_check.htm">Prev: Concept Checking
Introduction</a><br />
<a href="./creating_concepts.htm">Next: Creating Concept Checking
Classes</a><br /></p>
<hr />
As an example of using <tt>BOOST_CLASS_REQUIRE</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/tech/stl/Assignable.html">Assignable</a>.
We can check this by inserting
<tt>class_requires&lt;AssignableConcept&lt;T&gt; &gt;</tt> at the top
of the definition for <tt>std::vector</tt>.
<table>
<tr valign="top">
<td nowrap="nowrap">Copyright &copy; 2000</td>
<pre>
namespace std {
template &lt;class T&gt;
struct vector {
BOOST_CLASS_REQUIRE(T, boost, AssignableConcept);
...
};
}
</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_check.cpp"><tt>stl_concept_checks.cpp</tt></a>
gives and example of applying the concept checks to STL containers.
<p>
<a href="./concept_check.htm">Prev: Concept Checking Introduction</a> <br>
<a href="./creating_concepts.htm">Next: Creating Concept Checking Classes</a>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>)
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>
<td><a href="../../people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>), 2007
<a href="mailto:dave@boost-consulting.com">David Abrahams</a>.</td>
</tr>
</table>
</body>
</html>