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

View File

@ -1,54 +1,52 @@
<HTML> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<!-- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-- 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">
<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 <title>Concept Covering and Archetypes</title>
requirements (concepts) for the inputs to a component, but it is <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
equally important to verify that the chosen concepts <i>cover</i> the <link rel="stylesheet" href="../../rst.css" type="text/css" />
algorithm. That is, any possible user error should be caught by the </head>
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 <body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
href="http://www.sgi.com/tech/stl/InputIterator.html">Input "#FF0000">
Iterator</a> concept. Some care must be taken to ensure that the <img src="../../boost.png" alt="C++ Boost" width="277" height=
archetype is an exact match to the concept. For example, the concept "86" /><br clear="none" />
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.
<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> <pre>
template &lt;class T&gt; template &lt;class T&gt;
class input_iterator_archetype class input_iterator_archetype
@ -72,34 +70,32 @@ which must be verified by careful (manual) inspection.
}; };
</pre> </pre>
Generic algorithms are often tested by being instantiated with a <p>Generic algorithms are often tested by being instantiated with a number
number of common input types. For example, one might apply of common input types. For example, one might apply
<tt>std::stable_sort()</tt> with basic pointer types as the iterators. <tt>std::stable_sort()</tt> with basic pointer types as the iterators.
Though appropriate for testing the run-time behavior of the algorithm, Though appropriate for testing the run-time behavior of the algorithm, this
this is not helpful for ensuring concept coverage because C++ types is not helpful for ensuring concept coverage because C++ types never match
never match particular concepts, they often provide much more than the particular concepts exactly. Instead, they often provide more than the
minimal functionality required by any one concept. That is, even minimal functionality required by any one concept. Even though the function
though the function template compiles with a given type, the concept template has concept checks, and compiles with a given type, the checks may
requirements may still fall short of covering the functions actual still fall short of covering all the functionality that is actually used.
requirements. This is why it is important to compile with archetype This is why it is important to compile with archetype classes in addition
classes in addition to testing with common input types. 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.
<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> <pre>
{ {
typedef less_than_comparable_archetype&lt; typedef less_than_comparable_archetype&lt;
@ -109,18 +105,21 @@ layered archetype can be used.
} }
</pre> </pre>
<a href="./prog_with_concepts.htm">Next: Programming with Concepts</a><br> <p><a href="./prog_with_concepts.htm">Next: Programming with
<a href="./creating_concepts.htm">Prev: Creating Concept Checking Classes</a> Concepts</a><br />
<a href="./creating_concepts.htm">Prev: Creating Concept Checking
Classes</a><br />
<hr />
<br> <table>
<HR> <tr valign="top">
<TABLE> <td nowrap="nowrap">Copyright &copy; 2000</td>
<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> <td><a href="../../people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
</HTML> "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> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<!-- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-- 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">
<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 <body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
at how to create the corresponding checks for the "#FF0000">
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> <img src="../../boost.png" alt="C++ Boost" width="277" height=
RandomAccessIterator</a> concept. First, as a convention we name the "86" /><br clear="none" />
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.
<p> <h2><a name="creating-concept-checks" id="creating-concept-checks">Creating
The first part of the <tt>constraints()</tt> function includes Concept Checking Classes</a></h2>
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.
<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> <pre>
template &lt;class Iter&gt; template &lt;class X&gt;
struct RandomAccessIteratorConcept struct InputIterator
: Assignable&lt;X&gt;, EqualityComparable&lt;X&gt;
{ {
void constraints() { private:
function_requires&lt; BidirectionalIteratorConcept&lt;Iter&gt; &gt;(); typedef std::iterator_traits&lt;X&gt; t;
function_requires&lt; LessThanComparableConcept&lt;Iter&gt; &gt;(); public:
function_requires&lt; ConvertibleConcept&lt; typedef typename t::value_type value_type;
typename std::iterator_traits&lt;Iter&gt;::iterator_category, typedef typename t::difference_type difference_type;
std::random_access_iterator_tag&gt; &gt;(); typedef typename t::reference reference;
typedef typename t::pointer pointer;
typedef typename t::iterator_category iterator_category;
i += n; BOOST_CONCEPT_ASSERT((SignedInteger&lt;difference_type&gt;));
i = i + n; i = n + i; BOOST_CONCEPT_ASSERT((Convertible&lt;iterator_category, std::input_iterator_tag&gt;));
i -= n;
i = i - n; BOOST_CONCEPT_USAGE(InputIterator)
n = i - j; {
i[n]; 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> </pre>
One potential pitfall in designing concept checking classes is using <p>Unfortunately, that code wouldn't have worked out so well, because it
more expressions in the constraint function than necessary. For unintentionally imposes the requirement that <code>X</code> and its value
example, it is easy to accidentally use the default constructor to type are both default-constructible. On the other hand, since instances of
create the objects that will be needed in the expressions (and not all the <code>InputIterator</code> template will never be constructed, the
concepts require a default constructor). This is the reason we write compiler never has to check how its data members will be constructed (C++
the constraint function as a member function of a class. The objects Standard Section 14.7.1 9). For that reason you should <strong>always
involved in the expressions are declared as data members of the class. declare values needed for usage patterns as data members</strong>.</p>
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> <p>These sorts of errors in concept definitions can be detected by the use
<a href="./concept_covering.htm">Next: Concept Covering and Archetypes</a><br> of <a href="concept_covering.htm">Concept Archetypes</a>, but it's always
<a href="./using_concept_check.htm">Prev: Using Concept Checks</a> better to avoid them pre-emptively.</p>
<h3>Similarity to Proposed C++0x Language Support for Concepts</h3>
<br> <p>This library's syntaxes for concept refinement and for access of
<HR> associated types mirrors the corresponding <a href=
<TABLE> "http://www.generic-programming.org/languages/conceptcpp/">proposed</a>
<TR valign=top> syntaxes in C++0x. However, C++0x will use
<TD nowrap>Copyright &copy 2000</TD><TD> “signatures” rather than usage patterns to
<A HREF="../../people/jeremy_siek.htm">Jeremy Siek</A>(<A describe the valid operations on types participating in a concept, so when
HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>) converting your concept checking classes into language-supported concepts,
Andrew Lumsdaine</A>(<A HREF="mailto:lums@osl.iu.edu">lums@osl.iu.edu</A>) you'll need to translate your usage function into a series of
</TD></TR></TABLE> signatures.</p>
</BODY> <p><a href="./concept_covering.htm">Next: Concept Covering and
</HTML> 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; using namespace boost;
template<typename RanIter> template<typename RanIter>
BOOST_CONCEPT_WHERE( BOOST_CONCEPT_REQUIRES(
((Mutable_RandomAccessIterator<RanIter>)) ((Mutable_RandomAccessIterator<RanIter>))
((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>)) ((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>))

View File

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

View File

@ -1,8 +1,8 @@
// Copyright David Abrahams 2006. Distributed under the Boost // Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying // Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONCEPT_WHERE_DWA2006430_HPP #ifndef BOOST_CONCEPT_REQUIRES_DWA2006430_HPP
# define BOOST_CONCEPT_WHERE_DWA2006430_HPP # define BOOST_CONCEPT_REQUIRES_DWA2006430_HPP
# include <boost/parameter/aux_/parenthesized_type.hpp> # include <boost/parameter/aux_/parenthesized_type.hpp>
# include <boost/concept/assert.hpp> # include <boost/concept/assert.hpp>
@ -12,7 +12,7 @@ namespace boost {
// Template for use in handwritten assertions // Template for use in handwritten assertions
template <class Model, class More> template <class Model, class More>
struct where_ : More struct requires_ : More
{ {
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
typedef typename More::type type; typedef typename More::type type;
@ -23,41 +23,52 @@ struct where_ : More
// Template for use by macros, where models must be wrapped in parens. // 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 // This isn't in namespace detail to keep extra cruft out of resulting
// error messages. // error messages.
template <class ModelFn, class More> template <class ModelFn>
struct _where_ : More struct _requires_
{ {
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) enum { value = 0 };
typedef typename More::type type;
# endif
BOOST_CONCEPT_ASSERT_FN(ModelFn); BOOST_CONCEPT_ASSERT_FN(ModelFn);
}; };
#define BOOST_CONCEPT_WHERE_OPEN(r,data,t) ::boost::_where_<void(*)t, template <int check, class Result>
#define BOOST_CONCEPT_WHERE_CLOSE(r,data,t) > 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) #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 typename ::boost::parameter::aux::unaryfunptr_arg_type<void(*)result>::type
#elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) #elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
// Same thing as below without the initial typename // Same thing as below without the initial typename
# define BOOST_CONCEPT_WHERE(models, result) \ # define BOOST_CONCEPT_REQUIRES(models, result) \
BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_OPEN, ~, models) \ ::boost::Requires_< \
(0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \
::boost::parameter::aux::unaryfunptr_arg_type<void(*)result> \ ::boost::parameter::aux::unaryfunptr_arg_type<void(*)result> \
BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_CLOSE, ~, models)::type >::type
#else #else
// This just ICEs on MSVC6 :( // This just ICEs on MSVC6 :(
# define BOOST_CONCEPT_WHERE(models, result) \ # define BOOST_CONCEPT_REQUIRES(models, result) \
typename BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_OPEN, ~, models) \ typename ::boost::Requires_< \
::boost::parameter::aux::unaryfunptr_arg_type<void(*)result> \ (0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \
BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_CLOSE, ~, models)::type void(*)result \
>::type
#endif #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 } // 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)) 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) BOOST_CONCEPT_USAGE(Integer)
{ {
x.error_type_must_be_an_integer_type(); x.error_type_must_be_an_integer_type();
@ -90,9 +87,6 @@ namespace boost
# endif # endif
BOOST_concept(SignedInteger,(T)) { 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) { BOOST_CONCEPT_USAGE(SignedInteger) {
x.error_type_must_be_a_signed_integer_type(); x.error_type_must_be_a_signed_integer_type();
} }
@ -110,9 +104,6 @@ namespace boost
# endif # endif
BOOST_concept(UnsignedInteger,(T)) { 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) { BOOST_CONCEPT_USAGE(UnsignedInteger) {
x.error_type_must_be_an_unsigned_integer_type(); x.error_type_must_be_an_unsigned_integer_type();
} }
@ -135,9 +126,6 @@ namespace boost
BOOST_concept(DefaultConstructible,(TT)) 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) { BOOST_CONCEPT_USAGE(DefaultConstructible) {
TT a; // require default constructor TT a; // require default constructor
ignore_unused_variable_warning(a); ignore_unused_variable_warning(a);
@ -146,10 +134,6 @@ namespace boost
BOOST_concept(Assignable,(TT)) 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) { BOOST_CONCEPT_USAGE(Assignable) {
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
a = a; // require assignment operator a = a; // require assignment operator
@ -166,12 +150,9 @@ namespace boost
TT a; TT a;
}; };
BOOST_concept(CopyConstructible,(TT)) 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) { BOOST_CONCEPT_USAGE(CopyConstructible) {
TT a(b); // require copy constructor TT a(b); // require copy constructor
TT* ptr = &a; // require address of operator TT* ptr = &a; // require address of operator
@ -191,10 +172,6 @@ namespace boost
// The SGI STL version of Assignable requires copy constructor and operator= // The SGI STL version of Assignable requires copy constructor and operator=
BOOST_concept(SGIAssignable,(TT)) 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) { BOOST_CONCEPT_USAGE(SGIAssignable) {
TT b(a); TT b(a);
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
@ -216,9 +193,6 @@ namespace boost
BOOST_concept(Convertible,(X)(Y)) 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) { BOOST_CONCEPT_USAGE(Convertible) {
Y y = x; Y y = x;
ignore_unused_variable_warning(y); ignore_unused_variable_warning(y);
@ -244,9 +218,6 @@ namespace boost
BOOST_concept(EqualityComparable,(TT)) 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) { BOOST_CONCEPT_USAGE(EqualityComparable) {
require_boolean_expr(a == b); require_boolean_expr(a == b);
require_boolean_expr(a != b); require_boolean_expr(a != b);
@ -257,9 +228,6 @@ namespace boost
BOOST_concept(LessThanComparable,(TT)) 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) { BOOST_CONCEPT_USAGE(LessThanComparable) {
require_boolean_expr(a < b); require_boolean_expr(a < b);
} }
@ -270,9 +238,6 @@ namespace boost
// This is equivalent to SGI STL's LessThanComparable. // This is equivalent to SGI STL's LessThanComparable.
BOOST_concept(Comparable,(TT)) 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) { BOOST_CONCEPT_USAGE(Comparable) {
require_boolean_expr(a < b); require_boolean_expr(a < b);
require_boolean_expr(a > b); require_boolean_expr(a > b);
@ -283,18 +248,6 @@ namespace boost
TT a, b; 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) \ #define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
BOOST_concept(NAME, (First)(Second)) \ BOOST_concept(NAME, (First)(Second)) \
{ \ { \
@ -304,20 +257,7 @@ namespace boost
First a; \ First a; \
Second b; \ 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) \ #define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \
BOOST_concept(NAME, (Ret)(First)(Second)) \ BOOST_concept(NAME, (Ret)(First)(Second)) \
{ \ { \
@ -327,7 +267,6 @@ namespace boost
First a; \ First a; \
Second b; \ Second b; \
} }
#endif
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp); BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp);
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp); BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp);
@ -347,9 +286,6 @@ namespace boost
BOOST_concept(Generator,(Func)(Return)) 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>()); } BOOST_CONCEPT_USAGE(Generator) { test(is_void<Return>()); }
private: private:
@ -370,9 +306,6 @@ namespace boost
BOOST_concept(UnaryFunction,(Func)(Return)(Arg)) 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>()); } BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void<Return>()); }
private: private:
@ -394,9 +327,6 @@ namespace boost
BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second)) 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>()); } BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void<Return>()); }
private: private:
void test(boost::mpl::false_) void test(boost::mpl::false_)
@ -418,9 +348,6 @@ namespace boost
BOOST_concept(UnaryPredicate,(Func)(Arg)) 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) { BOOST_CONCEPT_USAGE(UnaryPredicate) {
require_boolean_expr(f(arg)); // require operator() returning bool require_boolean_expr(f(arg)); // require operator() returning bool
} }
@ -431,9 +358,6 @@ namespace boost
BOOST_concept(BinaryPredicate,(Func)(First)(Second)) 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) { BOOST_CONCEPT_USAGE(BinaryPredicate) {
require_boolean_expr(f(a, b)); // require operator() returning bool require_boolean_expr(f(a, b)); // require operator() returning bool
} }
@ -447,9 +371,6 @@ namespace boost
BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second)) BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second))
: 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) { BOOST_CONCEPT_USAGE(Const_BinaryPredicate) {
const_constraints(f); const_constraints(f);
} }
@ -468,9 +389,6 @@ namespace boost
{ {
typedef typename Func::result_type result_type; 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_USAGE(AdaptableGenerator)
{ {
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
@ -483,9 +401,6 @@ namespace boost
typedef typename Func::argument_type argument_type; typedef typename Func::argument_type argument_type;
typedef typename Func::result_type result_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() ~AdaptableUnaryFunction()
{ {
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); 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::second_argument_type second_argument_type;
typedef typename Func::result_type result_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() ~AdaptableBinaryFunction()
{ {
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
@ -520,18 +432,12 @@ namespace boost
: UnaryPredicate<Func, Arg> : UnaryPredicate<Func, Arg>
, AdaptableUnaryFunction<Func, bool, 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)) BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second))
: BinaryPredicate<Func, First, Second> : BinaryPredicate<Func, First, Second>
, AdaptableBinaryFunction<Func, bool, 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>::pointer pointer;
typedef typename boost::detail::iterator_traits<TT>::iterator_category iterator_category; typedef typename boost::detail::iterator_traits<TT>::iterator_category iterator_category;
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(InputIterator)
InputIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~InputIterator()
{ {
BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>)); BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>));
BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>)); BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));
@ -567,10 +470,7 @@ namespace boost
BOOST_concept(OutputIterator,(TT)(ValueT)) BOOST_concept(OutputIterator,(TT)(ValueT))
: Assignable<TT> : Assignable<TT>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(OutputIterator) {
OutputIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~OutputIterator() {
++i; // require preincrement operator ++i; // require preincrement operator
i++; // require postincrement operator i++; // require postincrement operator
@ -584,10 +484,7 @@ namespace boost
BOOST_concept(ForwardIterator,(TT)) BOOST_concept(ForwardIterator,(TT))
: InputIterator<TT> : InputIterator<TT>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(ForwardIterator)
ForwardIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~ForwardIterator()
{ {
BOOST_CONCEPT_ASSERT((Convertible< BOOST_CONCEPT_ASSERT((Convertible<
BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category
@ -605,10 +502,7 @@ namespace boost
BOOST_concept(Mutable_ForwardIterator,(TT)) BOOST_concept(Mutable_ForwardIterator,(TT))
: ForwardIterator<TT> : ForwardIterator<TT>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(Mutable_ForwardIterator) {
Mutable_ForwardIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_ForwardIterator() {
*i++ = *i; // require postincrement and assignment *i++ = *i; // require postincrement and assignment
} }
private: private:
@ -618,10 +512,7 @@ namespace boost
BOOST_concept(BidirectionalIterator,(TT)) BOOST_concept(BidirectionalIterator,(TT))
: ForwardIterator<TT> : ForwardIterator<TT>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(BidirectionalIterator)
BidirectionalIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~BidirectionalIterator()
{ {
BOOST_CONCEPT_ASSERT((Convertible< BOOST_CONCEPT_ASSERT((Convertible<
BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category
@ -639,10 +530,7 @@ namespace boost
: BidirectionalIterator<TT> : BidirectionalIterator<TT>
, Mutable_ForwardIterator<TT> , Mutable_ForwardIterator<TT>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(Mutable_BidirectionalIterator)
Mutable_BidirectionalIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_BidirectionalIterator()
{ {
*i-- = *i; // require postdecrement and assignment *i-- = *i; // require postdecrement and assignment
} }
@ -654,10 +542,7 @@ namespace boost
: BidirectionalIterator<TT> : BidirectionalIterator<TT>
, Comparable<TT> , Comparable<TT>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(RandomAccessIterator)
RandomAccessIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~RandomAccessIterator()
{ {
BOOST_CONCEPT_ASSERT((Convertible< BOOST_CONCEPT_ASSERT((Convertible<
BOOST_DEDUCED_TYPENAME BidirectionalIterator<TT>::iterator_category BOOST_DEDUCED_TYPENAME BidirectionalIterator<TT>::iterator_category
@ -682,10 +567,7 @@ namespace boost
: RandomAccessIterator<TT> : RandomAccessIterator<TT>
, Mutable_BidirectionalIterator<TT> , Mutable_BidirectionalIterator<TT>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(Mutable_RandomAccessIterator)
Mutable_RandomAccessIterator(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_RandomAccessIterator()
{ {
i[n] = *i; // require element access and assignment 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_pointer const_pointer;
typedef typename C::const_iterator const_iterator; typedef typename C::const_iterator const_iterator;
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(Container)
Container(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Container()
{ {
BOOST_CONCEPT_ASSERT((InputIterator<const_iterator>)); BOOST_CONCEPT_ASSERT((InputIterator<const_iterator>));
const_constraints(c); const_constraints(c);
@ -737,10 +616,7 @@ namespace boost
typedef typename C::iterator iterator; typedef typename C::iterator iterator;
typedef typename C::pointer pointer; typedef typename C::pointer pointer;
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(Mutable_Container)
Mutable_Container(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_Container()
{ {
BOOST_CONCEPT_ASSERT(( BOOST_CONCEPT_ASSERT((
Assignable<typename Mutable_Container::value_type>)); Assignable<typename Mutable_Container::value_type>));
@ -760,10 +636,7 @@ namespace boost
BOOST_concept(ForwardContainer,(C)) BOOST_concept(ForwardContainer,(C))
: Container<C> : Container<C>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(ForwardContainer)
ForwardContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~ForwardContainer()
{ {
BOOST_CONCEPT_ASSERT(( BOOST_CONCEPT_ASSERT((
ForwardIterator< ForwardIterator<
@ -776,10 +649,7 @@ namespace boost
: ForwardContainer<C> : ForwardContainer<C>
, Mutable_Container<C> , Mutable_Container<C>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(Mutable_ForwardContainer)
Mutable_ForwardContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_ForwardContainer()
{ {
BOOST_CONCEPT_ASSERT(( BOOST_CONCEPT_ASSERT((
Mutable_ForwardIterator< Mutable_ForwardIterator<
@ -795,10 +665,7 @@ namespace boost
C::const_reverse_iterator C::const_reverse_iterator
const_reverse_iterator; const_reverse_iterator;
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(ReversibleContainer)
ReversibleContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~ReversibleContainer()
{ {
BOOST_CONCEPT_ASSERT(( BOOST_CONCEPT_ASSERT((
BidirectionalIterator< BidirectionalIterator<
@ -823,10 +690,7 @@ namespace boost
{ {
typedef typename C::reverse_iterator reverse_iterator; typedef typename C::reverse_iterator reverse_iterator;
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(Mutable_ReversibleContainer)
Mutable_ReversibleContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_ReversibleContainer()
{ {
typedef typename Mutable_ForwardContainer<C>::iterator iterator; typedef typename Mutable_ForwardContainer<C>::iterator iterator;
BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<iterator>)); BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<iterator>));
@ -845,10 +709,7 @@ namespace boost
typedef typename C::size_type size_type; typedef typename C::size_type size_type;
typedef typename C::const_reference const_reference; typedef typename C::const_reference const_reference;
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(RandomAccessContainer)
RandomAccessContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~RandomAccessContainer()
{ {
BOOST_CONCEPT_ASSERT(( BOOST_CONCEPT_ASSERT((
RandomAccessIterator< RandomAccessIterator<
@ -875,10 +736,7 @@ namespace boost
private: private:
typedef Mutable_RandomAccessContainer self; typedef Mutable_RandomAccessContainer self;
public: public:
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(Mutable_RandomAccessContainer)
Mutable_RandomAccessContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Mutable_RandomAccessContainer()
{ {
BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::iterator>)); BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::iterator>));
BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::reverse_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 // ... so why aren't we following the standard? --DWA
, DefaultConstructible<S> , DefaultConstructible<S>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(Sequence)
Sequence(); // at least 2.96 and 3.4.3 both need this :(
#endif
~Sequence()
{ {
S S
c(n), c(n),
@ -940,10 +795,7 @@ namespace boost
BOOST_concept(FrontInsertionSequence,(S)) BOOST_concept(FrontInsertionSequence,(S))
: Sequence<S> : Sequence<S>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(FrontInsertionSequence)
FrontInsertionSequence(); // at least 2.96 and 3.4.3 both need this :(
#endif
~FrontInsertionSequence()
{ {
c.push_front(t); c.push_front(t);
c.pop_front(); c.pop_front();
@ -956,10 +808,7 @@ namespace boost
BOOST_concept(BackInsertionSequence,(S)) BOOST_concept(BackInsertionSequence,(S))
: Sequence<S> : Sequence<S>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(BackInsertionSequence)
BackInsertionSequence(); // at least 2.96 and 3.4.3 both need this :(
#endif
~BackInsertionSequence()
{ {
c.push_back(t); c.push_back(t);
c.pop_back(); c.pop_back();
@ -986,10 +835,7 @@ namespace boost
typedef typename C::value_compare value_compare; typedef typename C::value_compare value_compare;
typedef typename C::iterator iterator; typedef typename C::iterator iterator;
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(AssociativeContainer)
AssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~AssociativeContainer()
{ {
i = c.find(k); i = c.find(k);
r = c.equal_range(k); r = c.equal_range(k);
@ -1025,10 +871,7 @@ namespace boost
BOOST_concept(UniqueAssociativeContainer,(C)) BOOST_concept(UniqueAssociativeContainer,(C))
: AssociativeContainer<C> : AssociativeContainer<C>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(UniqueAssociativeContainer)
UniqueAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~UniqueAssociativeContainer()
{ {
C c(first, last); C c(first, last);
@ -1046,10 +889,7 @@ namespace boost
BOOST_concept(MultipleAssociativeContainer,(C)) BOOST_concept(MultipleAssociativeContainer,(C))
: AssociativeContainer<C> : AssociativeContainer<C>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(MultipleAssociativeContainer)
MultipleAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~MultipleAssociativeContainer()
{ {
C c(first, last); C c(first, last);
@ -1068,10 +908,7 @@ namespace boost
BOOST_concept(SimpleAssociativeContainer,(C)) BOOST_concept(SimpleAssociativeContainer,(C))
: AssociativeContainer<C> : AssociativeContainer<C>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(SimpleAssociativeContainer)
SimpleAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~SimpleAssociativeContainer()
{ {
typedef typename C::key_type key_type; typedef typename C::key_type key_type;
typedef typename C::value_type value_type; typedef typename C::value_type value_type;
@ -1082,10 +919,7 @@ namespace boost
BOOST_concept(PairAssociativeContainer,(C)) BOOST_concept(PairAssociativeContainer,(C))
: AssociativeContainer<C> : AssociativeContainer<C>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(PairAssociativeContainer)
PairAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~PairAssociativeContainer()
{ {
typedef typename C::key_type key_type; typedef typename C::key_type key_type;
typedef typename C::value_type value_type; typedef typename C::value_type value_type;
@ -1099,10 +933,7 @@ namespace boost
: AssociativeContainer<C> : AssociativeContainer<C>
, ReversibleContainer<C> , ReversibleContainer<C>
{ {
#if BOOST_WORKAROUND(__GNUC__, <= 3) BOOST_CONCEPT_USAGE(SortedAssociativeContainer)
SortedAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
#endif
~SortedAssociativeContainer()
{ {
C C
c(kc), c(kc),

View File

@ -1,56 +1,54 @@
<HTML> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<!-- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-- 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">
<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 <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>
<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" />
<h2><a name="programming-with-concepts" id=
"programming-with-concepts">Programming with Concepts</a></h2>
<p>The process of deciding how to group requirements into concepts and
deciding which concepts to use in each algorithm is perhaps the most deciding which concepts to use in each algorithm is perhaps the most
difficult (yet most important) part of building a generic library. difficult (yet most important) part of building a generic library. A
A guiding principle to use during this process is one we guiding principle to use during this process is one we call the
call the <i>requirement minimization principle</i>. <i>requirement minimization principle</i>.</p>
<p> <p><b>Requirement Minimization Principle:</b> Minimize the requirements on
<b>Requirement Minimization Principle:</b> Minimize the requirements the input parameters of a component to increase its reusability.</p>
on the input parameters of a component to increase its reusability.
<p> <p>There is natural tension in this statement. By definition, the input
There is natural tension in this statement. By definition, the input
parameters must be used by the component in order for the component to parameters must be used by the component in order for the component to
accomplish its task (by ``component'' we mean a function or class accomplish its task (by ``component'' we mean a function or class
template). The challenge then is to implement the component in such a template). The challenge then is to implement the component in such a way
way that makes the fewest assumptions (the minimum requirements) about that makes the fewest assumptions (the minimum requirements) about the
the inputs while still accomplishing the task. inputs while still accomplishing the task.</p>
<p> <p>The traditional notions of <i>abstraction</i> tie in directly to the
The traditional notions of <i>abstraction</i> tie in directly to the idea of minimal requirements. The more abstract the input, the fewer the
idea of minimal requirements. The more abstract the input, the fewer requirements. Thus, concepts are simply the embodiment of generic abstract
the requirements. Thus, concepts are simply the embodiment of generic data types in C++ template programming.</p>
abstract data types in C++ template programming.
<p> <p>When designing the concepts for some problem domain it is important to
When designing the concepts for some problem domain it is important to
keep in mind their purpose, namely to express the requirements for the keep in mind their purpose, namely to express the requirements for the
input to the components. With respect to the requirement minimization input to the components. With respect to the requirement minimization
principle, this means we want to minimize concepts. principle, this means we want to minimize concepts.
<!-- the following discussion does not match the Standard definition <!-- the following discussion does not match the Standard definition
of LessThanComparable and needs to be changed -Jeremy of LessThanComparable and needs to be changed -Jeremy
@ -88,7 +86,7 @@ principle because all of the comparison operators (<tt>&lt;</tt>,
<tt>></tt>, <tt><=</tt>, <tt>>=</tt>) are conceptually equivalent (in <tt>></tt>, <tt><=</tt>, <tt>>=</tt>) are conceptually equivalent (in
a mathematical sense). Adding conceptually equivalent valid a mathematical sense). Adding conceptually equivalent valid
expressions is not a violation of the requirement minimization 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. syntax. The added syntax increases re-usability.
<p> <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 <tt>std::stable_sort()</tt>, then the maintainer is given a reasonable
amount of flexibility within which to work. amount of flexibility within which to work.
--> --></p>
<p> <p>Minimality in concepts is a property associated with the underlying
Minimality in concepts is a property associated with the underlying semantics of the problem domain being represented. In the problem domain of
semantics of the problem domain being represented. In the problem basic containers, requiring traversal in a single direction is a smaller
domain of basic containers, requiring traversal in a single direction requirement than requiring traversal in both directions (hence the
is a smaller requirement than requiring traversal in both directions distinction between <a href=
(hence the distinction between <a "http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a> and
href="http://www.sgi.com/tech/stl/ForwardIterator.html"> <a href=
ForwardIterator</a> and "http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>).
<a The semantic difference can be easily seen in the difference between the
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html"> set of concrete data structures that have forward iterators versus the set
BidirectionalIterator</a>). The semantic difference can be easily seen that has bidirectional iterators. For example, singly-linked lists would
in the difference between the set of concrete data structures that fall in the set of data structures having forward iterators, but not
have forward iterators versus the set that has bidirectional bidirectional iterators. In addition, the set of algorithms that one can
iterators. For example, singly-linked lists would fall in the set of implement using only forward iterators is quite different than the set that
data structures having forward iterators, but not bidirectional can be implemented with bidirectional iterators. Because of this, it is
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 important to factor families of requirements into rather fine-grained
concepts. For example, the requirements for iterators are factored concepts. For example, the requirements for iterators are factored into the
into the six STL iterator concepts (trivial, output, input, forward, six STL iterator concepts (trivial, output, input, forward, bidirectional,
bidirectional, and random access). and random access).</p>
<p> <p><a href="./implementation.htm">Next: Implementation</a><br />
<a href="./implementation.htm">Next: Implementation</a><br> <a href="./concept_covering.htm">Prev: Concept Covering and
<a href="./concept_covering.htm">Prev: Concept Covering and Archetypes</a> Archetypes</a><br /></p>
<hr />
<br> <table>
<HR> <tr valign="top">
<TABLE> <td nowrap="nowrap">Copyright &copy; 2000</td>
<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> <td><a href="../../people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
</HTML> "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,230 +1,274 @@
<HTML> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<!-- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-- 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">
<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> <title>Boost Concept Checking Reference</title>
<LI><a href="#functions">Functions</a></LI> </head>
<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>
<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" />
<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> <pre>
template &lt;class Concept&gt; #include "boost/concept/assert.hpp"
void function_requires();
BOOST_CONCEPT_ASSERT((<em>concept checking class template specialization</em>));
</pre> </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>
<h3><a name="basic-concepts" id="basic-concepts">Basic Concept Checking
Classes</a></h3>
<pre> <pre>
// Apply concept checks in class definitions. #include "boost/concept_check.hpp"
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>);
</pre>
Deprecated macros:
<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>);
</pre>
<h3><a name="basic-concepts">Basic Concept Checking Classes</a></h3>
<pre>
template &lt;class T&gt;
struct IntegerConcept; // Is T a built-in integer type?
template &lt;class T&gt; template &lt;class T&gt;
struct SignedIntegerConcept; // Is T a built-in signed integer type? struct Integer; // Is T a built-in integer type?
template &lt;class T&gt; template &lt;class T&gt;
struct UnsignedIntegerConcept; // Is T a built-in unsigned integer type? 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; template &lt;class X, class Y&gt;
struct ConvertibleConcept; // Is X convertible to Y? struct Convertible; // Is X convertible to Y?
template &lt;class T&gt; template &lt;class T&gt;
struct <a href="../utility/Assignable.html">Assignable</a>Concept; // Standard ref 23.1 struct <a href=
"../utility/Assignable.html">Assignable</a>; // Standard ref 23.1
template &lt;class T&gt; template &lt;class T&gt;
struct SGI<a href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>Concept; struct SGI<a href=
"http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>;
template &lt;class T&gt; template &lt;class T&gt;
struct <a struct <a href=
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>Concept; "http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>;
template &lt;class T&gt; template &lt;class T&gt;
struct <a href="../utility/CopyConstructible.html">CopyConstructible</a>Concept; // Standard ref 20.1.3 struct <a href=
"../utility/CopyConstructible.html">CopyConstructible</a>; // Standard ref 20.1.3
template &lt;class T&gt; template &lt;class T&gt;
struct <a href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>Concept; // Standard ref 20.1.1 struct <a href=
"http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>; // Standard ref 20.1.1
template &lt;class T&gt; template &lt;class T&gt;
struct <a href="../utility/LessThanComparable.html">LessThanComparable</a>Concept; // Standard ref 20.1.2 struct <a href=
"../utility/LessThanComparable.html">LessThanComparable</a>; // Standard ref 20.1.2
template &lt;class T&gt; template &lt;class T&gt;
struct ComparableConcept; // The SGI STL <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a> concept struct Comparable; // The SGI STL <a href=
"http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a> concept
</pre> </pre>
<h3><a name="iterator-concepts">Iterator Concept Checking Classes</a></h3> <h3><a name="iterator-concepts" id="iterator-concepts">Iterator Concept
Checking Classes</a></h3>
<pre> <pre>
template &lt;class Iter&gt; 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 struct <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>; // Standard ref 24.1.1 Table 72
template &lt;class Iter, class T&gt; 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 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; 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 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; template &lt;class Iter&gt;
struct Mutable_ForwardIteratorConcept; struct Mutable_ForwardIterator;
template &lt;class Iter&gt; 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 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; template &lt;class Iter&gt;
struct Mutable_BidirectionalIteratorConcept; struct Mutable_BidirectionalIterator;
template &lt;class Iter&gt; 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 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; template &lt;class Iter&gt;
struct Mutable_RandomAccessIteratorConcept; struct Mutable_RandomAccessIterator;
</pre> </pre>
<h3><a name="function-object-concepts">Function Object Concept Checking Classes</a></h3> <h3><a name="function-object-concepts" id=
"function-object-concepts">Function Object Concept Checking
Classes</a></h3>
<pre> <pre>
#include "boost/concept_check.hpp"
template &lt;class Func, class Return&gt; template &lt;class Func, class Return&gt;
struct <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>Concept; struct <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>;
template &lt;class Func, class Return, class Arg&gt; template &lt;class Func, class Return, class Arg&gt;
struct <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">UnaryFunction</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/UnaryFunction.html">UnaryFunction</a>;
template &lt;class Func, class Return, class First, class Second&gt; 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; struct <a href=
"http://www.sgi.com/tech/stl/BinaryFunction.html">BinaryFunction</a>;
template &lt;class Func, class Arg&gt; template &lt;class Func, class Arg&gt;
struct Unary<a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>Concept; struct Unary<a href=
"http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>;
template &lt;class Func, class First, class Second&gt; template &lt;class Func, class First, class Second&gt;
struct <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>;
template &lt;class Func, class First, class Second&gt; template &lt;class Func, class First, class Second&gt;
struct Const_BinaryPredicateConcept; struct Const_BinaryPredicate;
template &lt;class Func, class Return&gt; template &lt;class Func, class Return&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableGenerator.html">AdaptableGenerator</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/AdaptableGenerator.html">AdaptableGenerator</a>;
template &lt;class Func, class Return, class Arg&gt; template &lt;class Func, class Return, class Arg&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>;
template &lt;class Func, class First, class Second&gt; template &lt;class Func, class First, class Second&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>;
template &lt;class Func, class Arg&gt; template &lt;class Func, class Arg&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptablePredicate.html">AdaptablePredicate</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/AdaptablePredicate.html">AdaptablePredicate</a>;
template &lt;class Func, class First, class Second&gt; template &lt;class Func, class First, class Second&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>;
</pre> </pre>
<h3><a name="container-concepts">Container Concept Checking Classes</a></h3> <h3><a name="container-concepts" id="container-concepts">Container Concept
Checking Classes</a></h3>
<pre> <pre>
template &lt;class C&gt; #include "boost/concept_check.hpp"
struct <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>Concept; // Standard ref 23.1 Table 65
template &lt;class C&gt; template &lt;class C&gt;
struct Mutable_ContainerConcept; struct <a href=
"http://www.sgi.com/tech/stl/Container.html">Container</a>; // Standard ref 23.1 Table 65
template &lt;class C&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/ForwardContainer.html">ForwardContainer</a>Concept; struct Mutable_Container;
template &lt;class C&gt; template &lt;class C&gt;
struct Mutable_ForwardContainerConcept; struct <a href=
"http://www.sgi.com/tech/stl/ForwardContainer.html">ForwardContainer</a>;
template &lt;class C&gt; 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 struct Mutable_ForwardContainer;
template &lt;class C&gt; template &lt;class C&gt;
struct Mutable_ReversibleContainerConcept; struct <a href=
"http://www.sgi.com/tech/stl/ReversibleContainer.html">ReversibleContainer</a>; // Standard ref 23.1 Table 66
template &lt;class C&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/RandomAccessContainer.html">RandomAccessContainer</a>Concept; struct Mutable_ReversibleContainer;
template &lt;class C&gt; template &lt;class C&gt;
struct Mutable_RandomAccessContainerConcept; struct <a href=
"http://www.sgi.com/tech/stl/RandomAccessContainer.html">RandomAccessContainer</a>;
template &lt;class C&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/Sequence.html">Sequence</a>Concept; // Standard ref 23.1.1 struct Mutable_RandomAccessContainer;
template &lt;class C&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/Sequence.html">Sequence</a>; // Standard ref 23.1.1
template &lt;class C&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/BackInsertionSequence.html">BackInsertionSequence</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>;
template &lt;class C&gt; 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 struct <a href=
"http://www.sgi.com/tech/stl/BackInsertionSequence.html">BackInsertionSequence</a>;
template &lt;class C&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>Concept; 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; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>;
template &lt;class C&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>;
template &lt;class C&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>;
template &lt;class C&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>Concept; 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> </pre>
<h3><a name="basic-archetype" id="basic-archetype">Basic Archetype
<h3><a name="basic-archetype">Basic Archetype Classes</a></h3> Classes</a></h3>
<pre> <pre>
#include "boost/concept_archetype.hpp"
template &lt;class T = int&gt; template &lt;class T = int&gt;
class null_archetype; // A type that models no concepts. class null_archetype; // A type that models no concepts.
@ -244,9 +288,11 @@ Deprecated macros:
class convertible_to_archetype; class convertible_to_archetype;
</pre> </pre>
<h3><a name="iterator-archetype">Iterator Archetype Classes</a></h3> <h3><a name="iterator-archetype" id="iterator-archetype">Iterator Archetype
Classes</a></h3>
<pre> <pre>
#include "boost/concept_archetype.hpp"
template &lt;class ValueType&gt; template &lt;class ValueType&gt;
class trivial_iterator_archetype; class trivial_iterator_archetype;
@ -264,12 +310,13 @@ Deprecated macros:
template &lt;class ValueType&gt; template &lt;class ValueType&gt;
class random_access_iterator_archetype; class random_access_iterator_archetype;
</pre> </pre>
<h3><a name="function-object-archetype">Function Object Archetype Classes</a></h3> <h3><a name="function-object-archetype" id=
"function-object-archetype">Function Object Archetype Classes</a></h3>
<pre> <pre>
#include "boost/concept_archetype.hpp"
template &lt;class Arg, class Return&gt; template &lt;class Arg, class Return&gt;
class unary_function_archetype; class unary_function_archetype;
@ -283,26 +330,62 @@ Deprecated macros:
class binary_predicate_archetype; class binary_predicate_archetype;
</pre> </pre>
<h3><a name="container-archetype">Container Archetype Classes</a></h3> <h3><a name="container-archetype" id="container-archetype">Container
Archetype Classes</a></h3>
<pre> <pre>
UNDER CONSTRUCTION UNDER CONSTRUCTION
</pre> </pre>
<p> <h3><a name="deprecated-functions" id="deprecated-functions">Deprecated
<a href="./concept_check.htm">Back to Introduction</a> Functions</a></h3>
<br> <pre>
<a href="./implementation.htm">Prev: Implementation</a> #include "boost/concept_check.hpp"
<br> template &lt;class Concept&gt;
<HR> void function_requires();
<TABLE> </pre>
<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> <h3><a name="deprecated-macros" id="deprecated-macros">Deprecated
</HTML> 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> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<!-- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-- 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">
<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 <body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
to make sure that a given type (or set of types) models the concept. "#FF0000">
The Boost Concept Checking Library (BCCL) includes concept checking classes <img src="../../boost.png" alt="C++ Boost" width="277" height=
for all of the concepts used in the C++ standard library and a few "86" /><br clear="none" />
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>.
<p> <h2><a name="using-concept-checks" id="using-concept-checks">Using Concept
An example of a concept checking class from the BCCL is the Checks</a></h2>
<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 <tt>EqualityComparableConcept</tt> class. The class corresponds to the
EqualityComparable requirements described in 20.1.1 of the C++ EqualityComparable requirements described in 20.1.1 of the C++ Standard,
Standard, and to the <a and to the <a href=
href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a> "http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>
concept documented in the SGI STL. concept documented in the SGI STL.</p>
<pre> <pre>
template &lt;class T&gt; template &lt;class T&gt;
struct EqualityComparableConcept; struct EqualityComparable;
</pre> </pre>
The template argument <tt>T</tt> will the type to be checked. That is, <p>The template argument is the type to be checked. That is, the purpose of
the purpose of <tt>EqualityComparableConcept</tt> is to make sure that <tt>EqualityComparable&lt;<em>X</em>&gt;</tt> is to make sure that
the template argument given for <tt>T</tt> models the <tt><em>X</em></tt> models the EqualityComparable concept.</p>
EqualityComparable concept.
<p> <h4><tt>BOOST_CONCEPT_ASSERT()</tt></h4>
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>function_requires()</tt></h4>
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.
<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> <pre>
// In my library: <font color="green">// In my library:</font>
template &lt;class T&gt; template &lt;class T&gt;
void generic_library_function(T x) void generic_library_function(T x)
{ {
function_requires&lt; EqualityComparableConcept&lt;T&gt; &gt;(); BOOST_CONCEPT_ASSERT<strong>((</strong>EqualityComparable&lt;T&gt;<strong>))</strong>;
// ... <font color="green">// ...</font>
}; };
// In the user's code: template &lt;class It&gt;
class generic_library_class
{
BOOST_CONCEPT_ASSERT<strong>((</strong>RandomAccessIterator&lt;It&gt;<strong>))</strong>;
<font color="green">// ...</font>
};
<font color="green">// In the user's code:</font>
class foo { class foo {
//... <font color="green">//... </font>
}; };
int main() { int main() {
foo f; foo x;
generic_library_function(f); generic_library_function(x);
return 0; generic_library_class&lt;std::vector&lt;char&gt;::iterator&gt; y;
<font color="green">//...</font>
} }
</pre> </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
The <tt>BOOST_CLASS_REQUIRE</tt> macro can be used inside a class for declaring concept constrained function templates</a> is the way that
definition to check whether some type models a concept. Make sure constraints are part of the function <em>declaration</em>, so clients will
that the arguments to this macro are simply identifiers. You may need see them. <code>BOOST_CONCEPT_ASSERT</code> can only express constraints
to use typedef to get your types into this form. 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>
<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> <pre>
// In my library: template&lt;typename RanIter&gt;
template &lt;class T&gt; BOOST_CONCEPT_REQUIRES(
struct generic_library_class ((Mutable_RandomAccessIterator&lt;RanIter&gt;))
{ ((LessThanComparable&lt;typename Mutable_RandomAccessIterator&lt;RanIter&gt;::value_type&gt;)),
BOOST_CLASS_REQUIRE(T, boost, EqualityComparableConcept); (void)) <font color="green">// return type</font>
// ... stable_sort(RanIter,RanIter);
};
// In the user's code:
class foo {
//...
};
int main() {
generic_library_class&lt;foo&gt; glc;
// ...
return 0;
}
</pre> </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> <p>Some concepts deal with more than one type. In this case the
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;();
...
}
</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 corresponding concept checking class will have multiple template
parameters. The following example shows how parameters. The following example shows how <tt>BOOST_CONCEPT_REQUIRES</tt>
<tt>function_requires()</tt> is used with the <a is used with the <a href=
href="../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a> "../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
concept which takes two type parameters: a property map and the key concept, which takes two type parameters: a property map and the key type
type for the map. for the map.</p>
<pre> <pre>
template &lt;class IncidenceGraph, class Buffer, class BFSVisitor, template &lt;class G, class Buffer, class BFSVisitor,
class ColorMap&gt; class ColorMap&gt;
void breadth_first_search(IncidenceGraph& g, 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, typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor s,
Buffer& Q, BFSVisitor vis, ColorMap color) Buffer&amp; Q, BFSVisitor vis, ColorMap color)
{ {
typedef typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor Vertex; typedef typename IncidenceGraph&lt;G&gt;::vertex_descriptor Vertex;
function_requires&lt; ReadWritePropertyMap&lt;ColorMap, Vertex&gt; &gt;();
... ...
} }
</pre> </pre>
<p>Although concept checks are designed for use by generic library
As an example of using <tt>BOOST_CLASS_REQUIRE</tt> we look at a concept implementors, they can also be useful to end users. Sometimes one may not
check that could be added to <tt>std::vector</tt>. One requirement be sure whether some type models a particular concept. The syntactic
that is placed on the element type is that it must be <a requirements, at least, can easily be checked by creating a small program
href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>. and using <tt>BOOST_CONCEPT_ASSERT</tt> with the type and concept in
We can check this by inserting question. For example:</p>
<tt>class_requires&lt;AssignableConcept&lt;T&gt; &gt;</tt> at the top
of the definition for <tt>std::vector</tt>.
<pre> <pre>
namespace std { <font color=
template &lt;class T&gt; "green">// Make sure list&lt;int&gt; has bidirectional iterators.</font>
struct vector { BOOST_CONCEPT_ASSERT((BidirectionalIterator&lt;std::list&lt;int&gt;::iterator&gt;));
BOOST_CLASS_REQUIRE(T, boost, AssignableConcept);
...
};
}
</pre> </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 />
Although the concept checks are designed for use by generic library <table>
implementors, they can also be useful to end users. Sometimes one may <tr valign="top">
not be sure whether some type models a particular concept. This can <td nowrap="nowrap">Copyright &copy; 2000</td>
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> <td><a href="../../people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
<a href="./concept_check.htm">Prev: Concept Checking Introduction</a> <br> "mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
<a href="./creating_concepts.htm">Next: Creating Concept Checking Classes</a> 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>
<br> </tr>
<HR> </table>
<TABLE> </body>
<TR valign=top> </html>
<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>