Full merge from trunk at revision 41356 of entire boost-root tree.

[SVN r41370]
This commit is contained in:
Beman Dawes
2007-11-25 18:38:02 +00:00
parent 92ae569516
commit 997b34b581
25 changed files with 1581 additions and 1202 deletions

View File

@@ -6,8 +6,20 @@ import testing ;
test-suite concept_check test-suite concept_check
: [ run stl_concept_covering.cpp ] : [ run stl_concept_covering.cpp ]
[ run stl_concept_check.cpp ]
[ run concept_check_test.cpp ] [ run concept_check_test.cpp ]
[ run class_concept_check_test.cpp ] [ run class_concept_check_test.cpp ]
[ compile-fail concept_check_fail_expected.cpp ] [ compile-fail concept_check_fail_expected.cpp ]
[ compile-fail class_concept_fail_expected.cpp ] [ compile-fail class_concept_fail_expected.cpp ]
[ run where.cpp ]
[ compile-fail where_fail.cpp ]
[ compile-fail usage_fail.cpp ]
# Backward compatibility tests
[ run old_concept_pass.cpp ]
[ compile-fail function_requires_fail.cpp ]
[ compile-fail old_concept_function_fail.cpp ]
[ compile-fail old_concept_class_fail.cpp ]
; ;

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,17 +1,10 @@
<HTML> <HTML>
<!-- <!-- Copyright (c) Jeremy Siek 2000 -->
-- Copyright (c) Jeremy Siek 2000 <!-- Distributed under the Boost -->
-- <!-- Software License, Version 1.0. (See accompanying -->
-- Permission to use, copy, modify, distribute and sell this software <!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
-- 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. Silicon Graphics makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head> <Head>
<Title>Boost Graph Library: Bibliography</Title> <Title>Boost Concept Checking Library: Bibliography</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b" <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000"> ALINK="#ff0000">
<IMG SRC="../../boost.png" <IMG SRC="../../boost.png"

View File

@@ -18,11 +18,11 @@ struct bar { bool operator()(int, char) { return true; } };
class class_requires_test class class_requires_test
{ {
BOOST_CLASS_REQUIRE(int, boost, EqualityComparableConcept); BOOST_CONCEPT_ASSERT((boost::EqualityComparable<int>));
typedef int* int_ptr; typedef const int* const_int_ptr; typedef int* int_ptr; typedef const int* const_int_ptr;
BOOST_CLASS_REQUIRE2(int_ptr, const_int_ptr, boost, EqualOpConcept); BOOST_CONCEPT_ASSERT((boost::EqualOp<int_ptr,const_int_ptr>));
BOOST_CLASS_REQUIRE3(foo, bool, int, boost, UnaryFunctionConcept); BOOST_CONCEPT_ASSERT((boost::UnaryFunction<foo,bool,int>));
BOOST_CLASS_REQUIRE4(bar, bool, int, char, boost, BinaryFunctionConcept); BOOST_CONCEPT_ASSERT((boost::BinaryFunction<bar,bool,int,char>));
}; };
int int

View File

@@ -1,4 +1,4 @@
// (C) Copyright Jeremy Siek 2000. // (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
// 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)
@@ -11,21 +11,22 @@
/* /*
This file verifies that class_requires of the Boost Concept Checking This file verifies that class_requires of the Boost Concept Checking
Library catches errors when it is suppose to. Library catches errors when it is supposed to.
*/ */
struct foo { }; struct foo { };
template <class T>
class class_requires_test class class_requires_test
{ {
BOOST_CLASS_REQUIRE(foo, boost, EqualityComparableConcept); BOOST_CONCEPT_ASSERT((boost::EqualityComparable<foo>));
}; };
int int
main() main()
{ {
class_requires_test x; class_requires_test<int> x;
(void)x; // suppress unused variable warning (void)x; // suppress unused variable warning
return 0; return 0;
} }

View File

@@ -1,313 +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>
<li>A mechanism for inserting compile-time checks on template parameters
<ul> at their point of use.</li>
<li>A mechanism for inserting compile-time checks of template
parameters.</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
to a generic algorithm. In C++, concepts are represented by formal
template parameters to function templates (generic algorithms).
However, C++ has no explicit mechanism for representing concepts ---
template parameters are merely placeholders. By convention, these
parameters are given names corresponding to the concept that is
required, but a C++ compiler does not enforce compliance to the
concept when the template parameter is bound to an actual type.
<p> <li><a href="#acknowledgements">Acknowledgements</a></li>
Naturally, if a generic algorithm is invoked with a type that does not
fulfill at least the syntactic requirements of the concept, a
compile-time error will occur. However, this error will not <i>per
se</i> reflect the fact that the type did not meet all of the
requirements of the concept. Rather, the error may occur deep inside
the instantiation hierarchy at the point where an expression is not
valid for the type, or where a presumed associated type is not
available. The resulting error messages are largely uninformative and
basically impenetrable.
<p> <li><a href="./using_concept_check.htm">Using Concept Checks</a></li>
What is required is a mechanism for enforcing ``concept safety'' at
(or close to) the point of instantiation. The Boost Concept Checking
Library uses some standard C++ constructs to enforce early concept
compliance and that provides more informative error messages upon
non-compliance.
<p> <li><a href="creating_concepts.htm">Creating Concept Checking
Note that this technique only addresses the syntactic Classes</a></li>
requirements of concepts (the valid expressions and associated types).
We do not address the semantic invariants or complexity guarantees,
which are also part of concept requirements..
<h2><a name="motivating-example">Motivating Example</a></h2> <li><a href="./concept_covering.htm">Concept Covering and
Archetypes</a></li>
We present a simple example to illustrate incorrect usage of a <li><a href="./prog_with_concepts.htm">Programming With Concepts</a></li>
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.
<pre> <li><a href="./implementation.htm">Implementation</a></li>
<li><a href="./reference.htm">Reference</a></li>
</ol>
<p><a href="../../people/jeremy_siek.htm">Jeremy Siek</a> contributed this
library. <a href="../../people/beman_dawes.html">Beman Dawes</a> managed
the formal review. <a href="../../people/dave_abrahams.htm">Dave
Abrahams</a> contributed a rewrite that updated syntax to be more
compatible with proposed syntax for concept support the C++ core
language.</p>
<h2><a name="introduction" id="introduction">Introduction</a></h2><p>A
<i>concept</i> is a set of requirements (valid expressions, associated
types, semantic invariants, complexity guarantees, etc.) that a type must
fulfill to be correctly used as arguments in a call to a generic algorithm.
In C++, concepts are represented by formal template parameters to function
templates (generic algorithms). However, C++ has no explicit mechanism for
representing concepts—template parameters are merely placeholders. By
convention, these parameters are given names corresponding to the concept
that is required, but a C++ compiler does not enforce compliance to the
concept when the template parameter is bound to an actual type.
<p>Naturally, if a generic algorithm is invoked with a type that does not
fulfill at least the syntactic requirements of the concept, a compile-time
error will occur. However, this error will not <i>per se</i> reflect the
fact that the type did not meet all of the requirements of the concept.
Rather, the error may occur deep inside the instantiation hierarchy at the
point where an expression is not valid for the type, or where a presumed
associated type is not available. The resulting error messages are largely
uninformative and basically impenetrable.</p>
<p>What is required is a mechanism for enforcing
“concept safety” at (or close to) the point
of instantiation. The Boost Concept Checking Library uses some standard C++
constructs to enforce early concept compliance and that provides more
informative error messages upon non-compliance.</p>
<p>Note that this technique only addresses the syntactic requirements of
concepts (the valid expressions and associated types). We do not address
the semantic invariants or complexity guarantees, which are also part of
concept requirements..</p>
<h2><a name="motivating-example" id="motivating-example">Motivating
Example</a></h2>
<p>We present a simple example to illustrate incorrect usage of a template
library and the resulting error messages. In the code below, the generic
<tt>std::stable_sort()</tt> algorithm from the Standard Template Library
(STL)[<a href="bibliography.htm#austern99:_gener_progr_stl">3</a>, <a href=
"bibliography.htm#IB-H965502">4</a>,<a href=
"bibliography.htm#stepa.lee-1994:the.s:TR">5</a>] is applied to a linked
list.</p>
<pre>
<a href="./bad_error_eg.cpp">bad_error_eg.cpp</a>: <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>
/usr/include/c++/4.1.2/bits/stl_algo.h: In function void std::
<pre> __insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with
stl_algo.h: In function `void __merge_sort_loop&lt;_List_iterator _RandomAccessIterator = __gnu_cxx::__normal_iterator&lt;std::complex&lt;float
&lt;int,int &amp;,int *&gt;, int *, int&gt;(_List_iterator&lt;int,int &amp;,int *&gt;, &gt;*, std::vector&lt;std::complex&lt;float&gt;, std::allocator&lt;std::complex&lt;
_List_iterator&lt;int,int &amp;,int *&gt;, int *, int)': float&gt; &gt; &gt; &gt;]:
stl_algo.h:1448: instantiated from `__merge_sort_with_buffer /usr/include/c++/4.1.2/bits/stl_algo.h:3066: instantiated from void
&lt;_List_iterator&lt;int,int &amp;,int *&gt;, int *, int&gt;( std::__inplace_stable_sort(_RandomAccessIterator,
_List_iterator&lt;int,int &amp;,int *&gt;, _List_iterator&lt;int,int &amp;,int *&gt;, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::
int *, int *)' __normal_iterator&lt;std::complex&lt;float&gt;*, std::vector&lt;std::complex&lt;
stl_algo.h:1485: instantiated from `__stable_sort_adaptive&lt; float&gt;, std::allocator&lt;std::complex&lt;float&gt; &gt; &gt; &gt;]
_List_iterator&lt;int,int &amp;,int *&gt;, int *, int&gt;(_List_iterator /usr/include/c++/4.1.2/bits/stl_algo.h:3776: instantiated from void
&lt;int,int &amp;,int *&gt;, _List_iterator&lt;int,int &amp;,int *&gt;, int *, int)' std::stable_sort(_RandomAccessIterator, _RandomAccessIterator) [with
stl_algo.h:1524: instantiated from here _RandomAccessIterator = __gnu_cxx::__normal_iterator&lt;std::complex&lt;float
stl_algo.h:1377: no match for `_List_iterator&lt;int,int &amp;,int *&gt; &amp; - &gt;*, std::vector&lt;std::complex&lt;float&gt;, std::allocator&lt;std::complex&lt;
_List_iterator&lt;int,int &amp;,int *&gt; &amp;' 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>
<pre> <li>With so many internal library functions listed in the error message,
boost/concept_check.hpp: In method `void LessThanComparableConcept the programmer could easily infer that the problem is in the library,
&lt;_List_iterator&lt;int,int &amp;,int *&gt; &gt;::constraints()': rather than in his or her own code.</li>
boost/concept_check.hpp:334: instantiated from `RandomAccessIteratorConcept </ol>
&lt;_List_iterator&lt;int,int &amp;,int *&gt; &gt;::constraints()'
bad_error_eg.cpp:6: instantiated from `stable_sort&lt;_List_iterator <p>The following is an example of what we might expect from a more
&lt;int,int &amp;,int *&gt; &gt;(_List_iterator&lt;int,int &amp;,int *&gt;, informative message (and is in fact what the Boost Concept Checking Library
_List_iterator&lt;int,int &amp;,int *&gt;)' produces):</p>
boost/concept_check.hpp:209: no match for `_List_iterator&lt;int,int &amp;,int *&gt; &amp; <pre>
&lt; _List_iterator&lt;int,int &amp;,int *&gt; &amp;' boost/concept_check.hpp: In destructor boost::LessThanComparable&lt;TT&gt;::~
LessThanComparable() [with TT = std::complex&lt;float&gt;]:
boost/concept/detail/general.hpp:29: instantiated from static void boost::
concept::requirement&lt;Model&gt;::failed() [with Model = boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;]
boost/concept/requires.hpp:30: instantiated from boost::_requires_&lt;void
(*)(boost::LessThanComparable&lt;std::complex&lt;float&gt; &gt;)&gt;
bad_error_eg.cpp:8: instantiated from here
boost/concept_check.hpp:236: error: no match for operator&lt; in ((boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;*)this)-&gt;boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;::a &lt; ((boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;*)this)-&gt;boost::
LessThanComparable&lt;std::complex&lt;float&gt; &gt;::b
</pre> </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> <ul>
<LI> The location of the error, <tt>bad_error_eg.cpp:6</tt> is <li>The message refers explicitly to concepts that the user can look up
specified in the error message. in the STL documentation (<a href=
<LI> The message refers explicitly to concepts that the user can look "http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a>).</li>
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> and
<tt>constraints()</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> <li>The error message is now much shorter and does not reveal
internal STL functions, nor indeed does it even point
to <code>std::stable_sort</code>.</li>
An earlier version of this concept checking system was developed by <li>The presence of <tt>concept_check.hpp</tt> in the error message
the author while working at SGI in their C++ compiler and library alerts the user to the fact that the error lies in the user code and not
group. The earlier version is now part of the SGI STL distribution. The in the library implementation.</li>
boost concept checking library differs from the concept checking in </ul>
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> <h2><a name="history" id="history">History</a></h2>
<ul> <p>The first version of this concept checking system was developed
<li><a href="http://www.oonumerics.org/tmpw00/"> by Jeremy Siek while working at SGI in their C++ compiler and
C++ Template Workshop 2000</a>, Concept Checking</li> library group. That version is now part of the SGI STL
</ul> distribution. The system originally introduced as the boost concept
checking library differs from concept checking in the SGI STL in
that the definition of concept checking classes was greatly
simplified, at the price of less helpful verbiage in the error
messages. In 2006 the system was rewritten (preserving backward
compatibility) by Dave Abrahams to be easier to use, more similar to
the proposed concept support the C++ core language, and to give
better error messages.
</p>
<h2><a name="acknowledgements">Acknowledgements</a></h2> <h2><a name="publications" id="publications">Publications</a></h2>
The idea to use function pointers to cause instantiation is due to <ul>
Alexander Stepanov. I am not sure of the origin of the idea to use <li><a href="http://www.oonumerics.org/tmpw00/">C++ Template Workshop
expressions to do up-front checking of templates, but it did appear in 2000</a>, Concept Checking</li>
D&amp;E[ </ul>
<a href="bibliography.htm#stroustrup94:_design_evolution">2</a>].
Thanks to Matt Austern for his excellent documentation and
organization of the STL concepts, upon which these concept checks
are based. Thanks to Boost members for helpful comments and
reviews.
<h2><a name="acknowledgements" id=
"acknowledgements">Acknowledgements</a></h2><p>The idea to use function
pointers to cause instantiation is due to Alexander Stepanov. We are not sure
of the origin of the idea to use expressions to do up-front checking of
templates, but it did appear in D&amp;E[ <a href=
"bibliography.htm#stroustrup94:_design_evolution">2</a>]. Thanks to Matt
Austern for his excellent documentation and organization of the STL
concepts, upon which these concept checks are based. Thanks to Boost
members for helpful comments and reviews.
<p> <p><a href="./using_concept_check.htm">Next: Using Concept
<a href="./using_concept_check.htm">Next: Using Concept Checks</a> Checks</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>.
</td>
</tr>
</table>
</body>
</html>

View File

@@ -1,4 +1,4 @@
// (C) Copyright Jeremy Siek 2000. // (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
// 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)
@@ -11,8 +11,8 @@
/* /*
This file verifies that function_requires() of the Boost Concept This file verifies that BOOST_CONCEPT_ASSERT catches errors in
Checking Library catches errors when it is suppose to. function context.
*/ */
@@ -21,6 +21,6 @@ struct foo { };
int int
main() main()
{ {
boost::function_requires< boost::EqualityComparableConcept<foo> >(); BOOST_CONCEPT_ASSERT((boost::EqualityComparable<foo>));
return 0; return 0;
} }

View File

@@ -25,76 +25,76 @@ main()
// Basic Concepts // Basic Concepts
{ {
typedef default_constructible_archetype<> foo; typedef default_constructible_archetype<> foo;
function_requires< DefaultConstructibleConcept<foo> >(); function_requires< DefaultConstructible<foo> >();
} }
{ {
typedef assignable_archetype<> foo; typedef assignable_archetype<> foo;
function_requires< AssignableConcept<foo> >(); function_requires< Assignable<foo> >();
} }
{ {
typedef copy_constructible_archetype<> foo; typedef copy_constructible_archetype<> foo;
function_requires< CopyConstructibleConcept<foo> >(); function_requires< CopyConstructible<foo> >();
} }
{ {
typedef sgi_assignable_archetype<> foo; typedef sgi_assignable_archetype<> foo;
function_requires< SGIAssignableConcept<foo> >(); function_requires< SGIAssignable<foo> >();
} }
{ {
typedef copy_constructible_archetype<> foo; typedef copy_constructible_archetype<> foo;
typedef convertible_to_archetype<foo> convertible_to_foo; typedef convertible_to_archetype<foo> convertible_to_foo;
function_requires< ConvertibleConcept<convertible_to_foo, foo> >(); function_requires< Convertible<convertible_to_foo, foo> >();
} }
{ {
function_requires< ConvertibleConcept<boolean_archetype, bool> >(); function_requires< Convertible<boolean_archetype, bool> >();
} }
{ {
typedef equality_comparable_archetype<> foo; typedef equality_comparable_archetype<> foo;
function_requires< EqualityComparableConcept<foo> >(); function_requires< EqualityComparable<foo> >();
} }
{ {
typedef less_than_comparable_archetype<> foo; typedef less_than_comparable_archetype<> foo;
function_requires< LessThanComparableConcept<foo> >(); function_requires< LessThanComparable<foo> >();
} }
{ {
typedef comparable_archetype<> foo; typedef comparable_archetype<> foo;
function_requires< ComparableConcept<foo> >(); function_requires< Comparable<foo> >();
} }
{ {
typedef equal_op_first_archetype<> First; typedef equal_op_first_archetype<> First;
typedef equal_op_second_archetype<> Second; typedef equal_op_second_archetype<> Second;
function_requires< EqualOpConcept<First, Second> >(); function_requires< EqualOp<First, Second> >();
} }
{ {
typedef not_equal_op_first_archetype<> First; typedef not_equal_op_first_archetype<> First;
typedef not_equal_op_second_archetype<> Second; typedef not_equal_op_second_archetype<> Second;
function_requires< NotEqualOpConcept<First, Second> >(); function_requires< NotEqualOp<First, Second> >();
} }
{ {
typedef less_than_op_first_archetype<> First; typedef less_than_op_first_archetype<> First;
typedef less_than_op_second_archetype<> Second; typedef less_than_op_second_archetype<> Second;
function_requires< LessThanOpConcept<First, Second> >(); function_requires< LessThanOp<First, Second> >();
} }
{ {
typedef less_equal_op_first_archetype<> First; typedef less_equal_op_first_archetype<> First;
typedef less_equal_op_second_archetype<> Second; typedef less_equal_op_second_archetype<> Second;
function_requires< LessEqualOpConcept<First, Second> >(); function_requires< LessEqualOp<First, Second> >();
} }
{ {
typedef greater_than_op_first_archetype<> First; typedef greater_than_op_first_archetype<> First;
typedef greater_than_op_second_archetype<> Second; typedef greater_than_op_second_archetype<> Second;
function_requires< GreaterThanOpConcept<First, Second> >(); function_requires< GreaterThanOp<First, Second> >();
} }
{ {
typedef greater_equal_op_first_archetype<> First; typedef greater_equal_op_first_archetype<> First;
typedef greater_equal_op_second_archetype<> Second; typedef greater_equal_op_second_archetype<> Second;
function_requires< GreaterEqualOpConcept<First, Second> >(); function_requires< GreaterEqualOp<First, Second> >();
} }
{ {
typedef copy_constructible_archetype<> Return; typedef copy_constructible_archetype<> Return;
typedef plus_op_first_archetype<Return> First; typedef plus_op_first_archetype<Return> First;
typedef plus_op_second_archetype<Return> Second; typedef plus_op_second_archetype<Return> Second;
function_requires< PlusOpConcept<Return, First, Second> >(); function_requires< PlusOp<Return, First, Second> >();
} }
//=========================================================================== //===========================================================================
@@ -102,70 +102,70 @@ main()
{ {
typedef generator_archetype<null_archetype<> > foo; typedef generator_archetype<null_archetype<> > foo;
function_requires< GeneratorConcept<foo, null_archetype<> > >(); function_requires< Generator<foo, null_archetype<> > >();
} }
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
{ {
function_requires< GeneratorConcept< void_generator_archetype, void > >(); function_requires< Generator< void_generator_archetype, void > >();
} }
#endif #endif
{ {
typedef unary_function_archetype<int, int> F; typedef unary_function_archetype<int, int> F;
function_requires< UnaryFunctionConcept<F, int, int> >(); function_requires< UnaryFunction<F, int, int> >();
} }
{ {
typedef binary_function_archetype<int, int, int> F; typedef binary_function_archetype<int, int, int> F;
function_requires< BinaryFunctionConcept<F, int, int, int> >(); function_requires< BinaryFunction<F, int, int, int> >();
} }
{ {
typedef unary_predicate_archetype<int> F; typedef unary_predicate_archetype<int> F;
function_requires< UnaryPredicateConcept<F, int> >(); function_requires< UnaryPredicate<F, int> >();
} }
{ {
typedef binary_predicate_archetype<int, int> F; typedef binary_predicate_archetype<int, int> F;
function_requires< BinaryPredicateConcept<F, int, int> >(); function_requires< BinaryPredicate<F, int, int> >();
} }
//=========================================================================== //===========================================================================
// Iterator Concepts // Iterator Concepts
{ {
typedef input_iterator_archetype<null_archetype<> > Iter; typedef input_iterator_archetype<null_archetype<> > Iter;
function_requires< InputIteratorConcept<Iter> >(); function_requires< InputIterator<Iter> >();
} }
{ {
typedef output_iterator_archetype<int> Iter; typedef output_iterator_archetype<int> Iter;
function_requires< OutputIteratorConcept<Iter, int> >(); function_requires< OutputIterator<Iter, int> >();
} }
{ {
typedef input_output_iterator_archetype<int> Iter; typedef input_output_iterator_archetype<int> Iter;
function_requires< InputIteratorConcept<Iter> >(); function_requires< InputIterator<Iter> >();
function_requires< OutputIteratorConcept<Iter, int> >(); function_requires< OutputIterator<Iter, int> >();
} }
{ {
typedef forward_iterator_archetype<null_archetype<> > Iter; typedef forward_iterator_archetype<null_archetype<> > Iter;
function_requires< ForwardIteratorConcept<Iter> >(); function_requires< ForwardIterator<Iter> >();
} }
{ {
typedef mutable_forward_iterator_archetype<assignable_archetype<> > Iter; typedef mutable_forward_iterator_archetype<assignable_archetype<> > Iter;
function_requires< Mutable_ForwardIteratorConcept<Iter> >(); function_requires< Mutable_ForwardIterator<Iter> >();
} }
{ {
typedef bidirectional_iterator_archetype<null_archetype<> > Iter; typedef bidirectional_iterator_archetype<null_archetype<> > Iter;
function_requires< BidirectionalIteratorConcept<Iter> >(); function_requires< BidirectionalIterator<Iter> >();
} }
{ {
typedef mutable_bidirectional_iterator_archetype<assignable_archetype<> > typedef mutable_bidirectional_iterator_archetype<assignable_archetype<> >
Iter; Iter;
function_requires< Mutable_BidirectionalIteratorConcept<Iter> >(); function_requires< Mutable_BidirectionalIterator<Iter> >();
} }
{ {
typedef random_access_iterator_archetype<null_archetype<> > Iter; typedef random_access_iterator_archetype<null_archetype<> > Iter;
function_requires< RandomAccessIteratorConcept<Iter> >(); function_requires< RandomAccessIterator<Iter> >();
} }
{ {
typedef mutable_random_access_iterator_archetype<assignable_archetype<> > typedef mutable_random_access_iterator_archetype<assignable_archetype<> >
Iter; Iter;
function_requires< Mutable_RandomAccessIteratorConcept<Iter> >(); function_requires< Mutable_RandomAccessIterator<Iter> >();
} }
//=========================================================================== //===========================================================================

View File

@@ -1,61 +1,59 @@
<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.
<pre> <h2><a name="concept-covering" id="concept-covering">Concept Covering and
template &lt;class T&gt; Archetypes</a></h2>
class input_iterator_archetype
{ <p>We have discussed how it is important to select the minimal requirements
private: (concepts) for the inputs to a component, but it is equally important to
verify that the chosen concepts <i>cover</i> the algorithm. That is, any
possible user error should be caught by the concept checks and not let slip
through. Concept coverage can be verified through the use of <i>archetype
classes</i>. An archetype class is an exact implementation of the interface
associated with a particular concept. The run-time behavior of the
archetype class is not important, the functions can be left empty. A simple
test program can then be compiled with the archetype classes as the inputs
to the component. If the program compiles then one can be sure that the
concepts cover the component. The following code shows the archetype class
for the <a href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a> concept. Some care must be taken to ensure that the archetype
is an exact match to the concept. For example, the concept states that the
return type of <tt>operator*()</tt> must be convertible to the value type.
It does not state the more stringent requirement that the return type be
<tt>T&amp;</tt> or <tt>const T&amp;</tt>. That means it would be a mistake
to use <tt>T&amp;</tt> or <tt>const T&amp;</tt> for the return type of the
archetype class. The correct approach is to create an artificial return
type that is convertible to <tt>T</tt>, as we have done here with
<tt>reference</tt>. The validity of the archetype class test is completely
dependent on it being an exact match with the concept, which must be
verified by careful (manual) inspection.</p>
<pre>
template &lt;class T&gt;
class input_iterator_archetype
{
private:
typedef input_iterator_archetype self; typedef input_iterator_archetype self;
public: public:
typedef std::input_iterator_tag iterator_category; typedef std::input_iterator_tag iterator_category;
typedef T value_type; typedef T value_type;
struct reference { struct reference {
@@ -69,58 +67,59 @@ which must be verified by careful (manual) inspection.
reference operator*() const { return reference(); } reference operator*() const { return reference(); }
self&amp; operator++() { return *this; } self&amp; operator++() { return *this; }
self operator++(int) { return *this; } self operator++(int) { return *this; }
}; };
</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> <p>The following is an excerpt from <a href=
The following is an excerpt from <a "./stl_concept_covering.cpp"><tt>stl_concept_covering.cpp</tt></a> that
href="./stl_concept_covering.cpp"><tt>stl_concept_covering.cpp</tt></a> shows how archetypes can be used to check the requirement documentation for
that shows how archetypes can be used to check the requirement <a href=
documentation for "http://www.sgi.com/tech/stl/stable_sort.html"><tt>std::stable_sort()</tt></a>.
<a href="http://www.sgi.com/tech/stl/stable_sort.html"> In this case, it looks like the <a href=
<tt>std::stable_sort()</tt></a>. In this case, it looks like the <a "../utility/CopyConstructible.html">CopyConstructible</a> and <a href=
href="../utility/CopyConstructible.html">CopyConstructible</a> and <a "../utility/Assignable.html">Assignable</a> requirements were forgotten in
href="../utility/Assignable.html">Assignable</a> requirements were the SGI STL documentation (try removing those archetypes). The Boost
forgotten in the SGI STL documentation (try removing those archetype classes have been designed so that they can be layered. In this
archetypes). The Boost archetype classes have been designed so that example the value type of the iterator is composed out of three archetypes.
they can be layered. In this example the value type of the iterator In the <a href="reference.htm#basic-archetype">archetype class
is composed out of three archetypes. In the archetype class reference reference</a>, template parameters named <tt>Base</tt> indicate where the
below, template parameters named <tt>Base</tt> indicate where the layered archetype paradigm can be used.</p>
layered archetype can be used. <pre>
{
<pre>
{
typedef less_than_comparable_archetype&lt; typedef less_than_comparable_archetype&lt;
sgi_assignable_archetype&lt;&gt; &gt; ValueType; sgi_assignable_archetype&lt;&gt; &gt; ValueType;
random_access_iterator_archetype&lt;ValueType&gt; ri; random_access_iterator_archetype&lt;ValueType&gt; ri;
std::stable_sort(ri, ri); std::stable_sort(ri, ri);
} }
</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> <p>As an example of how to create a concept checking class template, we
Next we check that the <tt>iterator_category</tt> of the iterator is look at how to create the corresponding checks for the <a href=
either <tt>std::random_access_iterator_tag</tt> or a derived class. "http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> concept.
After that we write out some code that corresponds to the valid The complete definition is here:</p>
expressions of the <a <pre>
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> template &lt;class X&gt;
RandomAccessIterator</a> concept. Typedefs can also be added to struct InputIterator
enforce the associated types of the concept. : Assignable&lt;X&gt;, EqualityComparable&lt;X&gt;
{
private:
typedef std::iterator_traits&lt;X&gt; t;
public:
typedef typename t::value_type value_type;
typedef typename t::difference_type difference_type;
typedef typename t::reference reference;
typedef typename t::pointer pointer;
typedef typename t::iterator_category iterator_category;
<pre> BOOST_CONCEPT_ASSERT((SignedInteger&lt;difference_type&gt;));
template &lt;class Iter&gt; BOOST_CONCEPT_ASSERT((Convertible&lt;iterator_category, std::input_iterator_tag&gt;));
struct RandomAccessIteratorConcept
BOOST_CONCEPT_USAGE(InputIterator)
{ {
void constraints() { X j(i); <font color=
function_requires&lt; BidirectionalIteratorConcept&lt;Iter&gt; &gt;(); "green">// require copy construction</font>
function_requires&lt; LessThanComparableConcept&lt;Iter&gt; &gt;(); same_type(*i++,v); <font color=
function_requires&lt; ConvertibleConcept&lt; "green">// require postincrement-dereference returning value_type</font>
typename std::iterator_traits&lt;Iter&gt;::iterator_category, X&amp; x = ++j; <font color=
std::random_access_iterator_tag&gt; &gt;(); "green">// require preincrement returning X&amp;</font>
i += n;
i = i + n; i = n + i;
i -= n;
i = i - n;
n = i - j;
i[n];
} }
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>

27
fake_sort.hpp Executable file
View File

@@ -0,0 +1,27 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP
# define BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP
# include <boost/detail/iterator.hpp>
# include <boost/concept/requires.hpp>
# include <boost/concept_check.hpp>
namespace fake
{
using namespace boost;
template<typename RanIter>
BOOST_CONCEPT_REQUIRES(
((Mutable_RandomAccessIterator<RanIter>))
((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>))
, (void))
sort(RanIter,RanIter)
{
}
}
#endif // BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP

26
function_requires_fail.cpp Executable file
View File

@@ -0,0 +1,26 @@
// (C) Copyright Jeremy Siek 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifdef NDEBUG
# undef NDEBUG
#endif
#include <boost/concept_check.hpp>
/*
This file verifies that function_requires() of the Boost Concept
Checking Library catches errors when it is suppose to.
*/
struct foo { };
int
main()
{
boost::function_requires< boost::EqualityComparable<foo> >();
return 0;
}

View File

@@ -1,50 +1,59 @@
<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
want the code to be compiled --- <i>but not executed</i>. Our
approach is to exercise the requirements in a separate function that
is assigned to a function pointer. In this case, the compiler will
instantiate the function but will not actually invoke it. In
addition, an optimizing compiler will remove the pointer assignment as
``dead code'' (though the run-time overhead added by the assignment
would be trivial in any case). It might be conceivable for a compiler
to skip the semantic analysis and compilation of the constraints
function in the first place, which would make our function pointer
technique ineffective. However, this is unlikely because removal of
unnecessary code and functions is typically done in later stages of a
compiler. We have successfully used the function pointer technique
with GNU C++, Microsoft Visual C++, and several EDG-based compilers
(KAI C++, SGI MIPSpro). The following code shows how this technique
can be applied to the <tt>std::stable_sort()</tt> function:
<pre> <h2><a name="warning" id="warning"><font color=
"red">Warning</font></a></h2>
<p><font color="red">This documentation is out-of-date; similar but
newer implementation techniques are now used. This documentation
also refers to components and protocols in the library's old
interace such as <code>BOOST_CLASS_REQUIRES</code>
and <code>constraints()</code> functions, which are still supported
but deprecated.</font></p>
<h2><a name="implementation" id="implementation">Implementation</a></h2>
<p>Ideally we would like to catch, and indicate, the concept violation at
the point of instantiation. As mentioned in D&amp;E[<a href=
"bibliography.htm#stroustrup94:_design_evolution">2</a>], the error can be
caught by exercising all of the requirements needed by the function
template. Exactly how the requirements (the valid expressions in
particular) are exercised is a tricky issue, since we want the code to be
compiled—<i>but not executed</i>. Our approach is to exercise the
requirements in a separate function that is assigned to a function pointer.
In this case, the compiler will instantiate the function but will not
actually invoke it. In addition, an optimizing compiler will remove the
pointer assignment as ``dead code'' (though the run-time overhead added by
the assignment would be trivial in any case). It might be conceivable for a
compiler to skip the semantic analysis and compilation of the constraints
function in the first place, which would make our function pointer
technique ineffective. However, this is unlikely because removal of
unnecessary code and functions is typically done in later stages of a
compiler. We have successfully used the function pointer technique with GNU
C++, Microsoft Visual C++, and several EDG-based compilers (KAI C++, SGI
MIPSpro). The following code shows how this technique can be applied to the
<tt>std::stable_sort()</tt> function:</p>
<pre>
template &lt;class RandomAccessIterator&gt; template &lt;class RandomAccessIterator&gt;
void stable_sort_constraints(RandomAccessIterator i) void stable_sort_constraints(RandomAccessIterator i)
{ {
@@ -57,24 +66,23 @@ can be applied to the <tt>std::stable_sort()</tt> function:
void stable_sort(RandomAccessIterator first, RandomAccessIterator last) 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,18 +98,14 @@ 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 <pre>
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
RandomAccessIterator</a>.
<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,16 +114,15 @@ 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,17 +131,16 @@ 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)(); \
template &lt;func##type_var##concept _Tp1&gt; \ template &lt;func##type_var##concept _Tp1&gt; \
@@ -148,14 +150,12 @@ typedef names to help prevent name collisions.
concept_checking_typedef_##type_var##concept 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
<tt>class_requires</tt> class which can be used inside the body of a <tt>class_requires</tt> class which can be used inside the body of a
@@ -184,21 +184,22 @@ Boost Concept Checking Library concept checks because several
compilers do not implement template parameters of function pointer 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>

28
old_concept_class_fail.cpp Executable file
View File

@@ -0,0 +1,28 @@
// (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Change Log:
// 20 Jan 2001 - Added warning suppression (David Abrahams)
#include "old_concepts.hpp"
// This file verifies that concepts written the old way still catch
// errors in class context. This is not expected to work on compilers
// without SFINAE support.
struct foo { };
class class_requires_test
{
BOOST_CLASS_REQUIRE(foo, old, EqualityComparableConcept);
};
int
main()
{
class_requires_test x;
(void)x; // suppress unused variable warning
return 0;
}

23
old_concept_function_fail.cpp Executable file
View File

@@ -0,0 +1,23 @@
// (C) Copyright Jeremy Siek 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifdef NDEBUG
# undef NDEBUG
#endif
#include "old_concepts.hpp"
// This file verifies that concepts written the old way still catch
// errors in function context. This is not expected to work on
// compilers without SFINAE support.
struct foo { };
int
main()
{
boost::function_requires< old::EqualityComparableConcept<foo> >();
return 0;
}

34
old_concept_pass.cpp Executable file
View File

@@ -0,0 +1,34 @@
// (C) Copyright Jeremy Siek, David Abrahams 2000-2006.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/concept_check.hpp>
#include "old_concepts.hpp"
// This test verifies that use of the old-style concept checking
// classes still compiles (but not that it detects constraint
// violations). We check them with the old-style macros just for
// completeness, since those macros stranslate into
// BOOST_CONCEPT_ASSERTs.
struct foo { bool operator()(int) { return true; } };
struct bar { bool operator()(int, char) { return true; } };
class class_requires_test
{
BOOST_CLASS_REQUIRE(int, old, EqualityComparableConcept);
typedef int* int_ptr; typedef const int* const_int_ptr;
BOOST_CLASS_REQUIRE2(int_ptr, const_int_ptr, old, EqualOpConcept);
BOOST_CLASS_REQUIRE3(foo, bool, int, old, UnaryFunctionConcept);
BOOST_CLASS_REQUIRE4(bar, bool, int, char, old, BinaryFunctionConcept);
};
int
main()
{
class_requires_test x;
boost::ignore_unused_variable_warning(x);
return 0;
}

67
old_concepts.hpp Executable file
View File

@@ -0,0 +1,67 @@
// Copyright Jeremy Siek, David Abrahams 2000-2006. Distributed under
// the Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP
# define BOOST_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP
#include <boost/concept_check.hpp>
namespace old
{
template <class TT>
void require_boolean_expr(const TT& t) {
bool x = t;
boost::ignore_unused_variable_warning(x);
}
template <class TT>
struct EqualityComparableConcept
{
void constraints() {
boost::require_boolean_expr(a == b);
boost::require_boolean_expr(a != b);
}
TT a, b;
};
template <class Func, class Return, class Arg>
struct UnaryFunctionConcept
{
// required in case any of our template args are const-qualified:
UnaryFunctionConcept();
void constraints() {
r = f(arg); // require operator()
}
Func f;
Arg arg;
Return r;
};
template <class Func, class Return, class First, class Second>
struct BinaryFunctionConcept
{
void constraints() {
r = f(first, second); // require operator()
}
Func f;
First first;
Second second;
Return r;
};
#define DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
template <class First, class Second> \
struct NAME { \
void constraints() { (void)constraints_(); } \
bool constraints_() { \
return a OP b; \
} \
First a; \
Second b; \
}
DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOpConcept);
}
#endif // BOOST_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP

View File

@@ -1,57 +1,55 @@
<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>
deciding which concepts to use in each algorithm is perhaps the most <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
difficult (yet most important) part of building a generic library. <link rel="stylesheet" href="../../rst.css" type="text/css" />
A guiding principle to use during this process is one we </head>
call the <i>requirement minimization principle</i>.
<p> <body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
<b>Requirement Minimization Principle:</b> Minimize the requirements "#FF0000">
on the input parameters of a component to increase its reusability. <img src="../../boost.png" alt="C++ Boost" width="277" height=
"86" /><br clear="none" />
<p> <h2><a name="programming-with-concepts" id=
There is natural tension in this statement. By definition, the input "programming-with-concepts">Programming with Concepts</a></h2>
parameters must be used by the component in order for the component to
accomplish its task (by ``component'' we mean a function or class
template). The challenge then is to implement the component in such a
way that makes the fewest assumptions (the minimum requirements) about
the inputs while still accomplishing the task.
<p> <p>The process of deciding how to group requirements into concepts and
The traditional notions of <i>abstraction</i> tie in directly to the deciding which concepts to use in each algorithm is perhaps the most
idea of minimal requirements. The more abstract the input, the fewer difficult (yet most important) part of building a generic library. A
the requirements. Thus, concepts are simply the embodiment of generic guiding principle to use during this process is one we call the
abstract data types in C++ template programming. <i>requirement minimization principle</i>.</p>
<p> <p><b>Requirement Minimization Principle:</b> Minimize the requirements on
When designing the concepts for some problem domain it is important to the input parameters of a component to increase its reusability.</p>
keep in mind their purpose, namely to express the requirements for the
input to the components. With respect to the requirement minimization
principle, this means we want to minimize concepts.
<!-- the following discussion does not match the Standard definition <p>There is natural tension in this statement. By definition, the input
parameters must be used by the component in order for the component to
accomplish its task (by ``component'' we mean a function or class
template). The challenge then is to implement the component in such a way
that makes the fewest assumptions (the minimum requirements) about the
inputs while still accomplishing the task.</p>
<p>The traditional notions of <i>abstraction</i> tie in directly to the
idea of minimal requirements. The more abstract the input, the fewer the
requirements. Thus, concepts are simply the embodiment of generic abstract
data types in C++ template programming.</p>
<p>When designing the concepts for some problem domain it is important to
keep in mind their purpose, namely to express the requirements for the
input to the components. With respect to the requirement minimization
principle, this means we want to minimize concepts.
<!-- the following discussion does not match the Standard definition
of LessThanComparable and needs to be changed -Jeremy of LessThanComparable and needs to be changed -Jeremy
<p> <p>
@@ -88,7 +86,7 @@ principle because all of the comparison operators (<tt>&lt;</tt>,
<tt>></tt>, <tt><=</tt>, <tt>>=</tt>) are conceptually equivalent (in <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 important to factor families of requirements into rather fine-grained
using only forward iterators is quite different than the set that can concepts. For example, the requirements for iterators are factored into the
be implemented with bidirectional iterators. Because of this, it is six STL iterator concepts (trivial, output, input, forward, bidirectional,
important to factor families of requirements into rather fine-grained and random access).</p>
concepts. For example, the requirements for iterators are factored
into the six STL iterator concepts (trivial, output, input, forward,
bidirectional, and random access).
<p> <p><a href="./implementation.htm">Next: Implementation</a><br />
<a href="./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,308 +1,408 @@
<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" />
<pre> <h2><a name="reference" id="reference">Reference</a></h2>
template &lt;class Concept&gt;
void function_requires(); <ol>
<li><a href="#macros">Macros</a></li>
<li><a href="#basic-concepts">Basic Concept Checking Classes</a></li>
<li><a href="#iterator-concepts">Iterator Concept Checking
Classes</a></li>
<li><a href="#function-object-concepts">Function Object Concept Checking
Classes</a></li>
<li><a href="#container-concepts">Container Concept Checking
Classes</a></li>
<li><a href="#basic-archetype">Basic Archetype Classes</a></li>
<li><a href="#iterator-archetype">Iterator Archetype Classes</a></li>
<li><a href="#function-object-archetype">Function Object Archetype
Classes</a></li>
<li><a href="#container-archetype">Container Archetype Classes</a></li>
<li><a href="#deprecated-functions">Deprecated Functions</a></li>
<li><a href="#deprecated-macros">Deprecated Macros</a></li>
<li><a href="#deprecated-concept-checking-classes">Deprecated Concept
Checking Classes</a></li>
</ol>
<h3><a name="macros" id="macros">Macros</a></h3>
<pre>
#include "boost/concept/assert.hpp"
BOOST_CONCEPT_ASSERT((<em>concept checking class template specialization</em>));
</pre> </pre>
<h3><a name="macros">Macros</a></h3> <p><strong>Effects:</strong> causes a compilation failure if the concept is
not satisfied.<br />
<strong>Note:</strong> this macro can be used at global, class, or function
scope.</p>
<pre> <pre>
// Apply concept checks in class definitions. #include "boost/concept/requires.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>); <font color="gray">template &lt;<em>template parameters</em>&gt;</font>
BOOST_CLASS_REQUIRE3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>namespace-of-concept</i>, <i>concept</i>); BOOST_CONCEPT_REQUIRES(
BOOST_CLASS_REQUIRE4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>namespace-of-concept</i>, <i>concept</i>); ((<em>concept checking class template specialization<sub>1</sub></em>))
((<em>concept checking class template specialization<sub>2</sub></em>))…
((<em>concept checking class template specialization<sub>n</sub></em>))<strong>,</strong>
(<em>function return type</em>)
) <font color="gray"><em>function_template_name</em>(…<em>function parameters</em>…)</font>
</pre> </pre>
Deprecated macros: <p><strong>Effects:</strong> causes a compilation failure if the
given concepts are not satisfied.<br />
<strong>Note:</strong> this macro is intended to be used in place of
a function template's return type.</p>
<pre> <h3><a name="basic-concepts" id="basic-concepts">Basic Concept Checking
// Apply concept checks in class definitions. Classes</a></h3>
BOOST_CLASS_REQUIRES(<i>type</i>, <i>concept</i>); <pre>
BOOST_CLASS_REQUIRES2(<i>type1</i>, <i>type2</i>, <i>concept</i>); #include "boost/concept_check.hpp"
BOOST_CLASS_REQUIRES3(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>concept</i>);
BOOST_CLASS_REQUIRES4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>); template &lt;class T&gt;
struct Integer; // Is T a built-in integer type?
template &lt;class T&gt;
struct SignedInteger; // Is T a built-in signed integer type?
template &lt;class T&gt;
struct UnsignedInteger; // Is T a built-in unsigned integer type?
template &lt;class X, class Y&gt;
struct Convertible; // Is X convertible to Y?
template &lt;class T&gt;
struct <a href=
"../utility/Assignable.html">Assignable</a>; // Standard ref 23.1
template &lt;class T&gt;
struct SGI<a href=
"http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>;
template &lt;class T&gt;
struct <a href=
"http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>;
template &lt;class T&gt;
struct <a href=
"../utility/CopyConstructible.html">CopyConstructible</a>; // Standard ref 20.1.3
template &lt;class T&gt;
struct <a href=
"http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>; // Standard ref 20.1.1
template &lt;class T&gt;
struct <a href=
"../utility/LessThanComparable.html">LessThanComparable</a>; // Standard ref 20.1.2
template &lt;class T&gt;
struct Comparable; // The SGI STL <a href=
"http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a> concept
</pre> </pre>
<h3><a name="basic-concepts">Basic Concept Checking Classes</a></h3> <h3><a name="iterator-concepts" id="iterator-concepts">Iterator Concept
Checking Classes</a></h3>
<pre>
template &lt;class Iter&gt;
struct <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>; // Standard ref 24.1.1 Table 72
<pre> template &lt;class Iter, class T&gt;
template &lt;class T&gt; struct <a href=
struct IntegerConcept; // Is T a built-in integer type? "http://www.sgi.com/tech/stl/OutputIterator.html">OutputIterator</a>; // Standard ref 24.1.2 Table 73
template &lt;class T&gt; template &lt;class Iter&gt;
struct SignedIntegerConcept; // Is T a built-in signed integer type? struct <a href=
"http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>; // Standard ref 24.1.3 Table 74
template &lt;class T&gt; template &lt;class Iter&gt;
struct UnsignedIntegerConcept; // Is T a built-in unsigned integer type? struct Mutable_ForwardIterator;
template &lt;class X, class Y&gt; template &lt;class Iter&gt;
struct ConvertibleConcept; // Is X convertible to Y? struct <a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>; // Standard ref 24.1.4 Table 75
template &lt;class T&gt; template &lt;class Iter&gt;
struct <a href="../utility/Assignable.html">Assignable</a>Concept; // Standard ref 23.1 struct Mutable_BidirectionalIterator;
template &lt;class T&gt; template &lt;class Iter&gt;
struct SGI<a href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>; // Standard ref 24.1.5 Table 76
template &lt;class T&gt; template &lt;class Iter&gt;
struct <a struct Mutable_RandomAccessIterator;
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>Concept;
template &lt;class T&gt;
struct <a href="../utility/CopyConstructible.html">CopyConstructible</a>Concept; // Standard ref 20.1.3
template &lt;class T&gt;
struct <a href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>Concept; // Standard ref 20.1.1
template &lt;class T&gt;
struct <a href="../utility/LessThanComparable.html">LessThanComparable</a>Concept; // Standard ref 20.1.2
template &lt;class T&gt;
struct ComparableConcept; // 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="function-object-concepts" id=
"function-object-concepts">Function Object Concept Checking
Classes</a></h3>
<pre>
#include "boost/concept_check.hpp"
<pre> template &lt;class Func, class Return&gt;
template &lt;class Iter&gt; struct <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>;
struct <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>Concept; // Standard ref 24.1.1 Table 72
template &lt;class Iter, class T&gt; template &lt;class Func, class Return, class Arg&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/UnaryFunction.html">UnaryFunction</a>;
template &lt;class Iter&gt; template &lt;class Func, class Return, class First, class Second&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/BinaryFunction.html">BinaryFunction</a>;
template &lt;class Iter&gt; template &lt;class Func, class Arg&gt;
struct Mutable_ForwardIteratorConcept; struct Unary<a href=
"http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>;
template &lt;class Iter&gt; template &lt;class Func, class First, class Second&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/BinaryPredicate.html">BinaryPredicate</a>;
template &lt;class Iter&gt; template &lt;class Func, class First, class Second&gt;
struct Mutable_BidirectionalIteratorConcept; struct Const_BinaryPredicate;
template &lt;class Iter&gt; template &lt;class Func, class Return&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/AdaptableGenerator.html">AdaptableGenerator</a>;
template &lt;class Iter&gt; template &lt;class Func, class Return, class Arg&gt;
struct Mutable_RandomAccessIteratorConcept; struct <a href=
"http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>;
template &lt;class Func, class First, class Second&gt;
struct <a href=
"http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>;
template &lt;class Func, class Arg&gt;
struct <a href=
"http://www.sgi.com/tech/stl/AdaptablePredicate.html">AdaptablePredicate</a>;
template &lt;class Func, class First, class Second&gt;
struct <a href=
"http://www.sgi.com/tech/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>;
</pre> </pre>
<h3><a name="function-object-concepts">Function Object Concept Checking Classes</a></h3> <h3><a name="container-concepts" id="container-concepts">Container Concept
Checking Classes</a></h3>
<pre>
#include "boost/concept_check.hpp"
<pre> template &lt;class C&gt;
template &lt;class Func, class Return&gt; struct <a href=
struct <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>Concept; "http://www.sgi.com/tech/stl/Container.html">Container</a>; // Standard ref 23.1 Table 65
template &lt;class Func, class Return, class Arg&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">UnaryFunction</a>Concept; struct Mutable_Container;
template &lt;class Func, class Return, class First, class Second&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/BinaryFunction.html">BinaryFunction</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/ForwardContainer.html">ForwardContainer</a>;
template &lt;class Func, class Arg&gt; template &lt;class C&gt;
struct Unary<a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>Concept; struct Mutable_ForwardContainer;
template &lt;class Func, class First, class Second&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/ReversibleContainer.html">ReversibleContainer</a>; // Standard ref 23.1 Table 66
template &lt;class Func, class First, class Second&gt; template &lt;class C&gt;
struct Const_BinaryPredicateConcept; struct Mutable_ReversibleContainer;
template &lt;class Func, class Return&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableGenerator.html">AdaptableGenerator</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/RandomAccessContainer.html">RandomAccessContainer</a>;
template &lt;class Func, class Return, class Arg&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>Concept; struct Mutable_RandomAccessContainer;
template &lt;class Func, class First, class Second&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/Sequence.html">Sequence</a>; // Standard ref 23.1.1
template &lt;class Func, class Arg&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptablePredicate.html">AdaptablePredicate</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>;
template &lt;class Func, class First, class Second&gt; template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>Concept; struct <a href=
"http://www.sgi.com/tech/stl/BackInsertionSequence.html">BackInsertionSequence</a>;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/AssociativeContainer.html">AssociativeContainer</a>; // Standard ref 23.1.2 Table 69
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>;
template &lt;class C&gt;
struct <a href=
"http://www.sgi.com/tech/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>;
</pre> </pre>
<h3><a name="container-concepts">Container Concept Checking Classes</a></h3> <h3><a name="basic-archetype" id="basic-archetype">Basic Archetype
Classes</a></h3>
<pre>
#include "boost/concept_archetype.hpp"
<pre> template &lt;class T = int&gt;
template &lt;class C&gt; class null_archetype; // A type that models no concepts.
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 Base = null_archetype&gt;
struct Mutable_ContainerConcept; class default_constructible_archetype;
template &lt;class C&gt; template &lt;class Base = null_archetype&gt;
struct <a href="http://www.sgi.com/tech/stl/ForwardContainer.html">ForwardContainer</a>Concept; class assignable_archetype;
template &lt;class C&gt; template &lt;class Base = null_archetype&gt;
struct Mutable_ForwardContainerConcept; class copy_constructible_archetype;
template &lt;class C&gt; template &lt;class Base = null_archetype&gt;
struct <a href="http://www.sgi.com/tech/stl/ReversibleContainer.html">ReversibleContainer</a>Concept; // Standard ref 23.1 Table 66 class equality_comparable_archetype;
template &lt;class C&gt; template &lt;class T, class Base = null_archetype&gt;
struct Mutable_ReversibleContainerConcept; class convertible_to_archetype;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/RandomAccessContainer.html">RandomAccessContainer</a>Concept;
template &lt;class C&gt;
struct Mutable_RandomAccessContainerConcept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/Sequence.html">Sequence</a>Concept; // Standard ref 23.1.1
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/BackInsertionSequence.html">BackInsertionSequence</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/AssociativeContainer.html">AssociativeContainer</a>Concept; // Standard ref 23.1.2 Table 69
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>Concept;
template &lt;class C&gt;
struct <a href="http://www.sgi.com/tech/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>Concept;
</pre> </pre>
<h3><a name="iterator-archetype" id="iterator-archetype">Iterator Archetype
Classes</a></h3>
<pre>
#include "boost/concept_archetype.hpp"
<h3><a name="basic-archetype">Basic Archetype Classes</a></h3> template &lt;class ValueType&gt;
class trivial_iterator_archetype;
<pre> template &lt;class ValueType&gt;
template &lt;class T = int&gt; class mutable_trivial_iterator_archetype;
class null_archetype; // A type that models no concepts.
template &lt;class Base = null_archetype&gt; template &lt;class ValueType&gt;
class default_constructible_archetype; class input_iterator_archetype;
template &lt;class Base = null_archetype&gt; template &lt;class ValueType&gt;
class assignable_archetype; class forward_iterator_archetype;
template &lt;class Base = null_archetype&gt; template &lt;class ValueType&gt;
class copy_constructible_archetype; class bidirectional_iterator_archetype;
template &lt;class Base = null_archetype&gt; template &lt;class ValueType&gt;
class equality_comparable_archetype; class random_access_iterator_archetype;
template &lt;class T, class Base = null_archetype&gt;
class convertible_to_archetype;
</pre> </pre>
<h3><a name="iterator-archetype">Iterator Archetype Classes</a></h3> <h3><a name="function-object-archetype" id=
"function-object-archetype">Function Object Archetype Classes</a></h3>
<pre>
#include "boost/concept_archetype.hpp"
<pre> template &lt;class Arg, class Return&gt;
template &lt;class ValueType&gt; class unary_function_archetype;
class trivial_iterator_archetype;
template &lt;class ValueType&gt; template &lt;class Arg1, class Arg2, class Return&gt;
class mutable_trivial_iterator_archetype; class binary_function_archetype;
template &lt;class ValueType&gt; template &lt;class Arg&gt;
class input_iterator_archetype; class predicate_archetype;
template &lt;class ValueType&gt;
class forward_iterator_archetype;
template &lt;class ValueType&gt;
class bidirectional_iterator_archetype;
template &lt;class ValueType&gt;
class random_access_iterator_archetype;
template &lt;class Arg1, class Arg2&gt;
class binary_predicate_archetype;
</pre> </pre>
<h3><a name="function-object-archetype">Function Object Archetype Classes</a></h3> <h3><a name="container-archetype" id="container-archetype">Container
Archetype Classes</a></h3>
<pre> <pre>
template &lt;class Arg, class Return&gt;
class unary_function_archetype;
template &lt;class Arg1, class Arg2, class Return&gt;
class binary_function_archetype;
template &lt;class Arg&gt;
class predicate_archetype;
template &lt;class Arg1, class Arg2&gt;
class binary_predicate_archetype;
</pre>
<h3><a name="container-archetype">Container Archetype Classes</a></h3>
<pre>
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

@@ -20,7 +20,7 @@
#include <vector> #include <vector>
#include <list> #include <list>
#include <deque> #include <deque>
#ifndef BOOST_NO_SLIST #if 0
#include <slist> #include <slist>
#endif #endif
@@ -43,27 +43,27 @@ main()
typedef std::list<int> List; typedef std::list<int> List;
// VC++ missing pointer and const_pointer typedefs // VC++ missing pointer and const_pointer typedefs
function_requires< Mutable_RandomAccessContainerConcept<Vector> >(); function_requires< Mutable_RandomAccessContainer<Vector> >();
function_requires< BackInsertionSequenceConcept<Vector> >(); function_requires< BackInsertionSequence<Vector> >();
#if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS)) #if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS))
#if !(defined(__sgi) && defined(BOOST_HIDE_EXPECTED_ERRORS)) #if !(defined(__sgi) && defined(BOOST_HIDE_EXPECTED_ERRORS))
// old deque iterator missing n + iter operation // old deque iterator missing n + iter operation
function_requires< Mutable_RandomAccessContainerConcept<Deque> >(); function_requires< Mutable_RandomAccessContainer<Deque> >();
#endif #endif
// warnings about signed and unsigned in old deque version // warnings about signed and unsigned in old deque version
function_requires< FrontInsertionSequenceConcept<Deque> >(); function_requires< FrontInsertionSequence<Deque> >();
function_requires< BackInsertionSequenceConcept<Deque> >(); function_requires< BackInsertionSequence<Deque> >();
#endif #endif
// VC++ missing pointer and const_pointer typedefs // VC++ missing pointer and const_pointer typedefs
function_requires< Mutable_ReversibleContainerConcept<List> >(); function_requires< Mutable_ReversibleContainer<List> >();
function_requires< FrontInsertionSequenceConcept<List> >(); function_requires< FrontInsertionSequence<List> >();
function_requires< BackInsertionSequenceConcept<List> >(); function_requires< BackInsertionSequence<List> >();
#ifndef BOOST_NO_SLIST #if 0
typedef BOOST_STD_EXTENSION_NAMESPACE::slist<int> SList; typedef BOOST_STD_EXTENSION_NAMESPACE::slist<int> SList;
function_requires< FrontInsertionSequenceConcept<SList> >(); function_requires< FrontInsertionSequence<SList> >();
#endif #endif
typedef std::set<int> Set; typedef std::set<int> Set;
@@ -71,21 +71,21 @@ main()
typedef std::map<int,int> Map; typedef std::map<int,int> Map;
typedef std::multimap<int,int> MultiMap; typedef std::multimap<int,int> MultiMap;
function_requires< SortedAssociativeContainerConcept<Set> >(); function_requires< SortedAssociativeContainer<Set> >();
function_requires< SimpleAssociativeContainerConcept<Set> >(); function_requires< SimpleAssociativeContainer<Set> >();
function_requires< UniqueAssociativeContainerConcept<Set> >(); function_requires< UniqueAssociativeContainer<Set> >();
function_requires< SortedAssociativeContainerConcept<MultiSet> >(); function_requires< SortedAssociativeContainer<MultiSet> >();
function_requires< SimpleAssociativeContainerConcept<MultiSet> >(); function_requires< SimpleAssociativeContainer<MultiSet> >();
function_requires< MultipleAssociativeContainerConcept<MultiSet> >(); function_requires< MultipleAssociativeContainer<MultiSet> >();
function_requires< SortedAssociativeContainerConcept<Map> >(); function_requires< SortedAssociativeContainer<Map> >();
function_requires< UniqueAssociativeContainerConcept<Map> >(); function_requires< UniqueAssociativeContainer<Map> >();
function_requires< PairAssociativeContainerConcept<Map> >(); function_requires< PairAssociativeContainer<Map> >();
function_requires< SortedAssociativeContainerConcept<MultiMap> >(); function_requires< SortedAssociativeContainer<MultiMap> >();
function_requires< MultipleAssociativeContainerConcept<MultiMap> >(); function_requires< MultipleAssociativeContainer<MultiMap> >();
function_requires< PairAssociativeContainerConcept<MultiMap> >(); function_requires< PairAssociativeContainer<MultiMap> >();
#endif #endif
return 0; return 0;

View File

@@ -177,7 +177,7 @@ main()
typedef equal_op_first_archetype<> Left; typedef equal_op_first_archetype<> Left;
typedef input_iterator_archetype<Left> InIter; typedef input_iterator_archetype<Left> InIter;
InIter in; InIter in;
function_requires< InputIteratorConcept<InIter> >(); function_requires< InputIterator<InIter> >();
equal_op_second_archetype<> value(dummy_cons); equal_op_second_archetype<> value(dummy_cons);
std::iterator_traits<InIter>::difference_type std::iterator_traits<InIter>::difference_type
n = std::count(in, in, value); n = std::count(in, in, value);
@@ -591,7 +591,7 @@ main()
std::nth_element(ri, ri, ri, comp); std::nth_element(ri, ri, ri, comp);
} }
{ {
#if defined(__GNUC__) || defined(__IBMCPP__) #if defined(__GNUC__)
typedef less_than_op_first_archetype<> FT; typedef less_than_op_first_archetype<> FT;
typedef less_than_op_second_archetype<> T; typedef less_than_op_second_archetype<> T;
#elif defined(__KCC) #elif defined(__KCC)
@@ -615,7 +615,7 @@ main()
fi = std::lower_bound(fi, fi, value, comp); fi = std::lower_bound(fi, fi, value, comp);
} }
{ {
#if defined(__GNUC__) || defined(__IBMCPP__) #if defined(__GNUC__)
// Note, order of T,FT is flipped from lower_bound // Note, order of T,FT is flipped from lower_bound
typedef less_than_op_second_archetype<> FT; typedef less_than_op_second_archetype<> FT;
typedef less_than_op_first_archetype<> T; typedef less_than_op_first_archetype<> T;
@@ -639,7 +639,7 @@ main()
fi = std::upper_bound(fi, fi, value, comp); fi = std::upper_bound(fi, fi, value, comp);
} }
{ {
#if defined(__GNUC__) || defined(__IBMCPP__) #if defined(__GNUC__)
typedef less_than_op_first_archetype< typedef less_than_op_first_archetype<
less_than_op_second_archetype< null_archetype<>, optag2>, optag1> FT; less_than_op_second_archetype< null_archetype<>, optag2>, optag1> FT;
typedef less_than_op_second_archetype< typedef less_than_op_second_archetype<
@@ -669,7 +669,7 @@ main()
ignore_unused_variable_warning(p); ignore_unused_variable_warning(p);
} }
{ {
#if defined(__GNUC__) || defined(__IBMCPP__) #if defined(__GNUC__)
typedef less_than_op_first_archetype< typedef less_than_op_first_archetype<
less_than_op_second_archetype<null_archetype<>, optag2>, optag1> FT; less_than_op_second_archetype<null_archetype<>, optag2>, optag1> FT;
typedef less_than_op_second_archetype< typedef less_than_op_second_archetype<
@@ -686,7 +686,7 @@ main()
{ {
typedef null_archetype<int> Arg1; typedef null_archetype<int> Arg1;
typedef null_archetype<char> Arg2; typedef null_archetype<char> Arg2;
#if defined(__GNUC__) || defined(__KCC) || defined(__IBMCPP__) #if defined(__GNUC__) || defined(__KCC)
typedef convertible_to_archetype<Arg1, typedef convertible_to_archetype<Arg1,
convertible_to_archetype<Arg2> > FT; convertible_to_archetype<Arg2> > FT;
typedef convertible_to_archetype<Arg2, typedef convertible_to_archetype<Arg2,
@@ -701,7 +701,7 @@ main()
} }
{ {
typedef null_archetype<> Tout; typedef null_archetype<> Tout;
#if defined(__GNUC__) || defined(__KCC) || defined(__IBMCPP__) #if defined(__GNUC__) || defined(__KCC)
typedef less_than_op_first_archetype< typedef less_than_op_first_archetype<
less_than_op_second_archetype< less_than_op_second_archetype<
convertible_to_archetype<Tout>, optag2>, optag1 > Tin1; convertible_to_archetype<Tout>, optag2>, optag1 > Tin1;

22
usage_fail.cpp Executable file
View File

@@ -0,0 +1,22 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/concept/usage.hpp>
template <class T>
struct StringInitializable
{
typedef int associated;
BOOST_CONCEPT_USAGE(StringInitializable)
{
T x = "foo";
}
};
// Test that accessing an associated type will actually exercise usage
// requirements
typedef StringInitializable<int>::associated tee;

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>
<tt>EqualityComparableConcept</tt> class. The class corresponds to the
EqualityComparable requirements described in 20.1.1 of the C++
Standard, and to the <a
href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>
concept documented in the SGI STL.
<pre> <p>For each concept there is a concept checking class template that can be
template &lt;class T&gt; used to make sure that a given type (or set of types) models the concept.
struct EqualityComparableConcept; The Boost Concept Checking Library (BCCL) includes concept checking class
templates for all of the concepts used in the C++ standard library and a
few more. See the <a href="./reference.htm">Reference</a> section for a
complete list. In addition, other boost libraries come with concept
checking classes for the concepts that are particular to those libraries.
For example, there are <a href="../graph/doc/graph_concepts.html">graph
concepts</a> and <a href="../property_map/property_map.html">property map
concepts</a>. Also, whenever <b>anyone</b> writing function templates needs
to express requirements that are not yet stated by an existing concept, a
new concept checking class should be created. How to do this is explained
in <a href="./creating_concepts.htm">Creating Concept Checking
Classes</a>.</p>
<p>An example of a concept checking class from the BCCL is the
<tt>EqualityComparableConcept</tt> class. The class corresponds to the
EqualityComparable requirements described in 20.1.1 of the C++ Standard,
and to the <a href=
"http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>
concept documented in the SGI STL.</p>
<pre>
template &lt;class T&gt;
struct EqualityComparable;
</pre> </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> <p>The most versatile way of checking concept requirements is to use the
<code>BOOST_CONCEPT_ASSERT()</code> macro. You can use this macro at any
scope, by passing a concept checking template specialization enclosed in
parentheses. <strong>Note:</strong> that means invocations of
<code>BOOST_CONCEPT_ASSERT</code> will appear to use <strong>double
parentheses</strong>.</p>
<pre>
<font color="green">// In my library:</font>
template &lt;class T&gt;
void generic_library_function(T x)
{
BOOST_CONCEPT_ASSERT<strong>((</strong>EqualityComparable&lt;T&gt;<strong>))</strong>;
<font color="green">// ...</font>
};
The <tt>function_requires()</tt> function can be used in function bodies template &lt;class It&gt;
and the <tt>BOOST_CLASS_REQUIRE</tt> macro can be used inside class class generic_library_class
bodies. The <tt>function_requires()</tt> function takes no arguments, {
but has a template parameter for the concept checking class. This BOOST_CONCEPT_ASSERT<strong>((</strong>RandomAccessIterator&lt;It&gt;<strong>))</strong>;
means that the instantiated concept checking class must be given as an <font color="green">// ...</font>
explicit template argument, as shown below. };
<pre> <font color="green">// In the user's code:</font>
// In my library: class foo {
template &lt;class T&gt; <font color="green">//... </font>
void generic_library_function(T x) };
{
function_requires&lt; EqualityComparableConcept&lt;T&gt; &gt;();
// ...
};
// In the user's code: int main() {
class foo { foo x;
//... generic_library_function(x);
}; generic_library_class&lt;std::vector&lt;char&gt;::iterator&gt; y;
<font color="green">//...</font>
int main() { }
foo f;
generic_library_function(f);
return 0;
}
</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
for declaring concept constrained function templates</a> is the way that
constraints are part of the function <em>declaration</em>, so clients will
see them. <code>BOOST_CONCEPT_ASSERT</code> can only express constraints
within the function template definition, which hides the constraint in the
function body. Aside from the loss of a self-documenting interface,
asserting conformance only in the function body can undesirably delay
checking if the function is explicitly instantiated in a different
translation unit from the one in which it is called, or if the compiler
does link-time instantiation.</p>
The <tt>BOOST_CLASS_REQUIRE</tt> macro can be used inside a class <p>The <tt>BOOST_CONCEPT_REQUIRES</tt> macro can be used in a function
definition to check whether some type models a concept. Make sure template declaration to check whether some type models a concept. It
that the arguments to this macro are simply identifiers. You may need accepts two arguments, a <strong>list of constraints</strong>, and the
to use typedef to get your types into this form. function template's return type. The list of constraints takes the form of
a sequence of adjacent concept checking template specializations,
<pre> <strong>in double parentheses</strong>, and the function's return type must
// In my library: also be parenthesized. For example, the standard <code>stable_sort</code>
template &lt;class T&gt; algorithm might be declared as follows: class</p>
struct generic_library_class <pre>
{ template&lt;typename RanIter&gt;
BOOST_CLASS_REQUIRE(T, boost, EqualityComparableConcept); BOOST_CONCEPT_REQUIRES(
// ... ((Mutable_RandomAccessIterator&lt;RanIter&gt;))
}; ((LessThanComparable&lt;typename Mutable_RandomAccessIterator&lt;RanIter&gt;::value_type&gt;)),
(void)) <font color="green">// return type</font>
// In the user's code: stable_sort(RanIter,RanIter);
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 corresponding concept checking class will have multiple template
href="./concept_check.htm#motivating-example">motivating example</a>, parameters. The following example shows how <tt>BOOST_CONCEPT_REQUIRES</tt>
one good application of concept checks would be to insert is used with the <a href=
<tt>function_requires()</tt> at the top of <tt>std::stable_sort()</tt> "../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
to make sure the template parameter type models <a concept, which takes two type parameters: a property map and the key type
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> for the map.</p>
RandomAccessIterator</a>. In addition, <tt>std::stable_sort()</tt> <pre>
requires that the <tt>value_type</tt> of the iterators be template &lt;class G, class Buffer, class BFSVisitor,
<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
parameters. The following example shows how
<tt>function_requires()</tt> is used with the <a
href="../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
concept which takes two type parameters: a property map and the key
type for the map.
<pre>
template &lt;class IncidenceGraph, class Buffer, class BFSVisitor,
class ColorMap&gt; 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 <pre>
of the definition for <tt>std::vector</tt>. <font color=
"green">// Make sure list&lt;int&gt; has bidirectional iterators.</font>
<pre> BOOST_CONCEPT_ASSERT((BidirectionalIterator&lt;std::list&lt;int&gt;::iterator&gt;));
namespace std {
template &lt;class T&gt;
struct vector {
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>

13
where.cpp Executable file
View File

@@ -0,0 +1,13 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <vector>
#undef NDEBUG
#include "fake_sort.hpp"
int main()
{
std::vector<int> v;
fake::sort(v.begin(), v.end());
return 0;
}

13
where_fail.cpp Executable file
View File

@@ -0,0 +1,13 @@
// Copyright David Abrahams 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <list>
#undef NDEBUG
#include "fake_sort.hpp"
int main()
{
std::list<int> v;
fake::sort(v.begin(), v.end());
return 0;
}