forked from boostorg/concept_check
Updated Concept Check library documentation.
Changed BOOST_CONCEPT_WHERE to BOOST_CONCEPT_REQUIRES to be more consistent with the current C++0x proposal, which now uses a "requires" keyword in lieu of "where." Factored GCC workarounds into the BOOST_CONCEPT_USAGE macro. [SVN r40769]
This commit is contained in:
@ -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;
|
|
||||||
}
|
|
||||||
|
@ -1,312 +1,330 @@
|
|||||||
<HTML>
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
<!--
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
-- Copyright (c) Jeremy Siek and Andrew Lumsdaine 2000
|
|
||||||
--
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
-- Permission to use, copy, modify, distribute and sell this software
|
<!-- Copyright (c) 2000 Jeremy Siek and Andrew Lumsdaine, 2007 David Abrahams -->
|
||||||
-- and its documentation for any purpose is hereby granted without fee,
|
<!-- Distributed under the Boost -->
|
||||||
-- provided that the above copyright notice appears in all copies and
|
<!-- Software License, Version 1.0. (See accompanying -->
|
||||||
-- that both that copyright notice and this permission notice appear
|
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||||
-- in supporting documentation. We make no
|
|
||||||
-- representations about the suitability of this software for any
|
<head>
|
||||||
-- purpose. It is provided "as is" without express or implied warranty.
|
<meta name="generator" content=
|
||||||
-->
|
"HTML Tidy for Linux/x86 (vers 1 September 2005), see www.w3.org" />
|
||||||
<Head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
<Title>Concept Check Library</Title>
|
|
||||||
|
<title>Concept Check Library</title>
|
||||||
|
<link rel="stylesheet" href="../../rst.css" type="text/css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
||||||
ALINK="#ff0000">
|
"#FF0000">
|
||||||
<IMG SRC="../../boost.png"
|
<img src="../../boost.png" alt="C++ Boost" width="277" height=
|
||||||
ALT="C++ Boost" width="277" height="86">
|
"86" /><br clear="none" />
|
||||||
|
|
||||||
<BR Clear>
|
<h1>The Boost Concept Check Library (BCCL)</h1>
|
||||||
|
|
||||||
<H1>The Boost Concept Check Library (BCCL)</H1>
|
<blockquote>
|
||||||
|
The Concept Check library allows one to add explicit statement and
|
||||||
|
checking of <a href=
|
||||||
|
"../../more/generic_programming.html#concept">concepts</a> in the style
|
||||||
|
of the <a href=
|
||||||
|
"http://www.generic-programming.org/languages/conceptcpp/specification/">proposed
|
||||||
|
C++ language extension</a>.
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
<h2>
|
<h2><a name="sec:concept-checking" id="sec:concept-checking"></a>Synopsis</a></h2>
|
||||||
<A NAME="sec:concept-checking"></A>
|
|
||||||
header <a href="../../boost/concept_check.hpp">
|
|
||||||
<tt>boost/concept_check.hpp</tt></a>
|
|
||||||
<br>and <a href="../../boost/concept_archetype.hpp">
|
|
||||||
<tt>boost/concept_archetype.hpp</tt></a>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>
|
<p>Generic programming in C++ is characterized by the use of template
|
||||||
Generic programming in C++ is characterized by the use of template
|
parameters to represent abstract data types (or “<a href=
|
||||||
parameters to represent abstract data types (or ``concepts'').
|
"../../more/generic_programming.html#concept">concepts</a>”). However, the
|
||||||
However, the C++ language itself does not provide a mechanism for the
|
C++ language itself does not provide a mechanism for the writer of a class
|
||||||
writer of a class or function template to explicitly state what
|
or function template to explicitly state the concept that the user-supplied
|
||||||
concept the user-supplied template argument should model (or conform
|
template argument should model (or conform to). Template parameters are
|
||||||
to). The common practice is to name the template parameter after the
|
commonly named after the concept they're required to model as a hint to the
|
||||||
required concept as a hint to the user and to state the concept
|
user, and to make the concept requirements explicit in code. However, the
|
||||||
requirements in the documentation. However, often times the
|
compiler doesn't treat these special names specially: a parameter named
|
||||||
requirements are vague, incorrect, or nonexistent, which is quite a
|
<code>RandomAccessIterator</code> is no different to the compiler than one
|
||||||
problem for the user, since he or she will not know exactly what kind
|
named <code>T</code>. Furthermore,</p>
|
||||||
of input is expected by the template. Furthermore, the following
|
|
||||||
problems occur:
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Compiler error messages resulting from incorrect template
|
<li>Compiler error messages resulting from incorrect template arguments
|
||||||
arguments can be particularly difficult to decipher. Often times
|
can be particularly difficult to decipher. Often times the error does not
|
||||||
the error does not point to the location of the template
|
point to the location of the template call-site, but instead exposes the
|
||||||
call-site, but instead exposes the internals of the template, which
|
internals of the template, which the user should never have to see.</li>
|
||||||
the user should never have to see.</li>
|
|
||||||
|
|
||||||
<li>The documented concept requirements may not fully <i>cover</i>
|
<li>Without checking from the compiler, the documented requirements are
|
||||||
the template, meaning the user could get a compiler error even
|
oftentimes vague, incorrect, or nonexistent, so a user cannot know
|
||||||
though the supplied template arguments meet the documented
|
exactly what kind of arguments are expected.</li>
|
||||||
requirements.</li>
|
|
||||||
|
|
||||||
<li>The documented concept requirements may be too stringent,
|
<li>The documented concept requirements may not fully <i>cover</i> the
|
||||||
requiring more than is really needed by the template.</li>
|
needs of the actual template, meaning the user could get a compiler error
|
||||||
|
even though the supplied template arguments meet the documented
|
||||||
|
requirements.</li>
|
||||||
|
|
||||||
<li>The requirements are not explicitly stated in the code, which
|
<li>The documented concept requirements may be too stringent, requiring
|
||||||
makes the code harder to understand. Also, the code may
|
more than is really needed by the template.</li>
|
||||||
get out-of-sync with the documented requirements.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
The Boost Concept Checking Library provides:
|
<li>Concept names in code may drift out-of-sync with the documented
|
||||||
|
requirements.</li>
|
||||||
|
</ul><p>The Boost Concept Checking Library provides:
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>A mechanism for inserting compile-time checks of template
|
<li>A mechanism for inserting compile-time checks on template parameters
|
||||||
parameters.</li>
|
at their point of use.</li>
|
||||||
|
|
||||||
<li>A framework for specifying concept requirements though concept
|
<li>A framework for specifying concept requirements though concept
|
||||||
checking classes.</li>
|
checking classes.</li>
|
||||||
|
|
||||||
<li>A mechanism for verifying that concept requirements cover the template.</li>
|
<li>A mechanism for verifying that concept requirements cover the
|
||||||
|
template.</li>
|
||||||
|
|
||||||
<li>A suite of concept checking classes and archetype classes that
|
<li>A suite of concept checking classes and archetype classes that match
|
||||||
match the concept requirements in the C++ Standard Library.</li>
|
the concept requirements in the C++ Standard Library.</li>
|
||||||
</ul>
|
|
||||||
|
|
||||||
The mechanisms use standard C++ and introduce no run-time
|
<li>An alternative to the use of traits classes for accessing associated
|
||||||
overhead. The main cost of using the mechanism is in compile-time.
|
types that mirrors the syntax proposed for the next C++ standard.</li>
|
||||||
|
</ul><p>The mechanisms use standard C++ and introduce no run-time overhead.
|
||||||
|
The main cost of using the mechanism is in compile-time.</p>
|
||||||
|
|
||||||
<p>
|
<p><strong>Every programmer writing class or function templates ought to
|
||||||
Any programmer writing class or function templates ought to make
|
make concept checking a normal part of their code writing routine.</strong>
|
||||||
concept checking a normal part of their code writing routine. A
|
A concept check should be inserted for each template parameter in a
|
||||||
concept check should be inserted for each template parameter in a
|
component's public interface. If the concept is one of the ones from the
|
||||||
component's public interface. If the concept is one of the ones from
|
Standard Library, then simply use the matching concept checking class in
|
||||||
the Standard Library, then simply use the matching concept checking
|
the BCCL. If not, then write a new concept checking class - after all, they
|
||||||
class in the BCCL. If not, then write a new concept checking class -
|
are typically only a few lines long. For new concepts, a matching archetype
|
||||||
after all, they are typically only a few lines long. For new concepts,
|
class should also be created, which is a minimal skeleton-implementation of
|
||||||
a matching archetype class should also be created, which is a minimal
|
the concept</p>
|
||||||
skeleton-implementation of the concept
|
|
||||||
|
|
||||||
<p>
|
<p>The documentation is organized into the following sections.</p>
|
||||||
The documentation is organized into the following sections.
|
|
||||||
|
|
||||||
<OL>
|
<ol>
|
||||||
<LI><a href="#introduction">Introduction</a></LI>
|
<li><a href="#introduction">Introduction</a></li>
|
||||||
<LI><a href="#motivating-example">Motivating Example</a></LI>
|
|
||||||
<LI><a href="#history">History</a></LI>
|
|
||||||
<LI><a href="#publications">Publications</a></LI>
|
|
||||||
<LI><a href="#acknowledgements">Acknowledgements</a></LI>
|
|
||||||
<LI><a href="./using_concept_check.htm">Using Concept Checks</a></LI>
|
|
||||||
<LI><a href="creating_concepts.htm">Creating Concept Checking Classes</a></LI>
|
|
||||||
<LI><a href="./concept_covering.htm">Concept Covering and Archetypes</a></LI>
|
|
||||||
<LI><a href="./prog_with_concepts.htm" ">Programming With Concepts</a></LI>
|
|
||||||
<LI><a href="./implementation.htm">Implementation</a></LI>
|
|
||||||
<LI><a href="./reference.htm">Reference</a></LI>
|
|
||||||
</OL>
|
|
||||||
|
|
||||||
<p>
|
<li><a href="#motivating-example">Motivating Example</a></li>
|
||||||
<a href="../../people/jeremy_siek.htm">Jeremy Siek</a> contributed
|
|
||||||
this library. <a href="../../people/beman_dawes.html">Beman Dawes</a>
|
|
||||||
managed the formal review.
|
|
||||||
|
|
||||||
<h2><a name="introduction">Introduction</a></h2>
|
<li><a href="#history">History</a></li>
|
||||||
|
|
||||||
A <i>concept</i> is a set of requirements (valid expressions,
|
|
||||||
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="#publications">Publications</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="#acknowledgements">Acknowledgements</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="./using_concept_check.htm">Using Concept Checks</a></li>
|
||||||
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..
|
|
||||||
|
|
||||||
<h2><a name="motivating-example">Motivating Example</a></h2>
|
<li><a href="creating_concepts.htm">Creating Concept Checking
|
||||||
|
Classes</a></li>
|
||||||
|
|
||||||
We present a simple example to illustrate incorrect usage of a
|
<li><a href="./concept_covering.htm">Concept Covering and
|
||||||
template library and the resulting error messages. In the code below,
|
Archetypes</a></li>
|
||||||
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="./prog_with_concepts.htm">Programming With Concepts</a></li>
|
||||||
|
|
||||||
|
<li><a href="./implementation.htm">Implementation</a></li>
|
||||||
|
|
||||||
|
<li><a href="./reference.htm">Reference</a></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p><a href="../../people/jeremy_siek.htm">Jeremy Siek</a> contributed this
|
||||||
|
library. <a href="../../people/beman_dawes.html">Beman Dawes</a> managed
|
||||||
|
the formal review. <a href="../../people/dave_abrahams.htm">Dave
|
||||||
|
Abrahams</a> contributed a rewrite that updated syntax to be more
|
||||||
|
compatible with proposed syntax for concept support the C++ core
|
||||||
|
language.</p>
|
||||||
|
|
||||||
|
<h2><a name="introduction" id="introduction">Introduction</a></h2><p>A
|
||||||
|
<i>concept</i> is a set of requirements (valid expressions, associated
|
||||||
|
types, semantic invariants, complexity guarantees, etc.) that a type must
|
||||||
|
fulfill to be correctly used as arguments in a call to a generic algorithm.
|
||||||
|
In C++, concepts are represented by formal template parameters to function
|
||||||
|
templates (generic algorithms). However, C++ has no explicit mechanism for
|
||||||
|
representing concepts—template parameters are merely placeholders. By
|
||||||
|
convention, these parameters are given names corresponding to the concept
|
||||||
|
that is required, but a C++ compiler does not enforce compliance to the
|
||||||
|
concept when the template parameter is bound to an actual type.
|
||||||
|
|
||||||
|
<p>Naturally, if a generic algorithm is invoked with a type that does not
|
||||||
|
fulfill at least the syntactic requirements of the concept, a compile-time
|
||||||
|
error will occur. However, this error will not <i>per se</i> reflect the
|
||||||
|
fact that the type did not meet all of the requirements of the concept.
|
||||||
|
Rather, the error may occur deep inside the instantiation hierarchy at the
|
||||||
|
point where an expression is not valid for the type, or where a presumed
|
||||||
|
associated type is not available. The resulting error messages are largely
|
||||||
|
uninformative and basically impenetrable.</p>
|
||||||
|
|
||||||
|
<p>What is required is a mechanism for enforcing
|
||||||
|
“concept safety” at (or close to) the point
|
||||||
|
of instantiation. The Boost Concept Checking Library uses some standard C++
|
||||||
|
constructs to enforce early concept compliance and that provides more
|
||||||
|
informative error messages upon non-compliance.</p>
|
||||||
|
|
||||||
|
<p>Note that this technique only addresses the syntactic requirements of
|
||||||
|
concepts (the valid expressions and associated types). We do not address
|
||||||
|
the semantic invariants or complexity guarantees, which are also part of
|
||||||
|
concept requirements..</p>
|
||||||
|
|
||||||
|
<h2><a name="motivating-example" id="motivating-example">Motivating
|
||||||
|
Example</a></h2>
|
||||||
|
|
||||||
|
<p>We present a simple example to illustrate incorrect usage of a template
|
||||||
|
library and the resulting error messages. In the code below, the generic
|
||||||
|
<tt>std::stable_sort()</tt> algorithm from the Standard Template Library
|
||||||
|
(STL)[<a href="bibliography.htm#austern99:_gener_progr_stl">3</a>, <a href=
|
||||||
|
"bibliography.htm#IB-H965502">4</a>,<a href=
|
||||||
|
"bibliography.htm#stepa.lee-1994:the.s:TR">5</a>] is applied to a linked
|
||||||
|
list.</p>
|
||||||
|
<pre>
|
||||||
<a href="./bad_error_eg.cpp">bad_error_eg.cpp</a>:
|
<a href="./bad_error_eg.cpp">bad_error_eg.cpp</a>:
|
||||||
1 #include <list>
|
<font color="gray">1</font> #include <vector>
|
||||||
2 #include <algorithm>
|
<font color="gray">2</font color="gray"> #include <complex>
|
||||||
3
|
<font color="gray">3</font color="gray"> #include <algorithm>
|
||||||
4 int main(int, char*[]) {
|
<font color="gray">4</font color="gray">
|
||||||
5 std::list<int> 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<std::complex<float> > 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 <class RandomAccessIterator>
|
template <class RandomAccessIterator>
|
||||||
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<_List_iterator
|
_RandomAccessIterator = __gnu_cxx::__normal_iterator<std::complex<float
|
||||||
<int,int &,int *>, int *, int>(_List_iterator<int,int &,int *>,
|
>*, std::vector<std::complex<float>, std::allocator<std::complex<
|
||||||
_List_iterator<int,int &,int *>, int *, int)':
|
float> > > >]’:
|
||||||
stl_algo.h:1448: instantiated from `__merge_sort_with_buffer
|
/usr/include/c++/4.1.2/bits/stl_algo.h:3066: instantiated from ‘void
|
||||||
<_List_iterator<int,int &,int *>, int *, int>(
|
std::__inplace_stable_sort(_RandomAccessIterator,
|
||||||
_List_iterator<int,int &,int *>, _List_iterator<int,int &,int *>,
|
_RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::
|
||||||
int *, int *)'
|
__normal_iterator<std::complex<float>*, std::vector<std::complex<
|
||||||
stl_algo.h:1485: instantiated from `__stable_sort_adaptive<
|
float>, std::allocator<std::complex<float> > > >]’
|
||||||
_List_iterator<int,int &,int *>, int *, int>(_List_iterator
|
/usr/include/c++/4.1.2/bits/stl_algo.h:3776: instantiated from ‘void
|
||||||
<int,int &,int *>, _List_iterator<int,int &,int *>, int *, int)'
|
std::stable_sort(_RandomAccessIterator, _RandomAccessIterator) [with
|
||||||
stl_algo.h:1524: instantiated from here
|
_RandomAccessIterator = __gnu_cxx::__normal_iterator<std::complex<float
|
||||||
stl_algo.h:1377: no match for `_List_iterator<int,int &,int *> & -
|
>*, std::vector<std::complex<float>, std::allocator<std::complex<
|
||||||
_List_iterator<int,int &,int *> &'
|
float> > > >]’
|
||||||
|
bad_error_eg.cpp:8: instantiated from here
|
||||||
|
/usr/include/c++/4.1.2/bits/stl_algo.h:2277: error: no match for
|
||||||
|
‘operator<’ in ‘__val < __first. __gnu_cxx::__normal_iterator<
|
||||||
|
_Iterator, _Container>::operator* [with _Iterator = std::complex<float
|
||||||
|
>*, _Container = std::vector<std::complex<float>, std::allocator<
|
||||||
|
std::complex<float> > >]()’
|
||||||
</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<float></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,
|
||||||
<_List_iterator<int,int &,int *> >::~LessThanComparableConcept()':
|
rather than in his or her own code.</li>
|
||||||
boost/concept_check.hpp:334: instantiated from `RandomAccessIteratorConcept
|
</ol>
|
||||||
<_List_iterator<int,int &,int *> >::~RandomAccessIteratorConcept()'
|
|
||||||
bad_error_eg.cpp:6: instantiated from `stable_sort<_List_iterator
|
<p>The following is an example of what we might expect from a more
|
||||||
<int,int &,int *> >(_List_iterator<int,int &,int *>,
|
informative message (and is in fact what the Boost Concept Checking Library
|
||||||
_List_iterator<int,int &,int *>)'
|
produces):</p>
|
||||||
boost/concept_check.hpp:209: no match for `_List_iterator<int,int &,int *> &
|
<pre>
|
||||||
< _List_iterator<int,int &,int *> &'
|
boost/concept_check.hpp: In destructor ‘boost::LessThanComparable<TT>::~
|
||||||
|
LessThanComparable() [with TT = std::complex<float>]’:
|
||||||
|
boost/concept/detail/general.hpp:29: instantiated from ‘static void boost::
|
||||||
|
concept::requirement<Model>::failed() [with Model = boost::
|
||||||
|
LessThanComparable<std::complex<float> >]’
|
||||||
|
boost/concept/requires.hpp:30: instantiated from ‘boost::_requires_<void
|
||||||
|
(*)(boost::LessThanComparable<std::complex<float> >)>’
|
||||||
|
bad_error_eg.cpp:8: instantiated from here
|
||||||
|
boost/concept_check.hpp:236: error: no match for ‘operator<’ in ‘((boost::
|
||||||
|
LessThanComparable<std::complex<float> >*)this)->boost::
|
||||||
|
LessThanComparable<std::complex<float> >::a < ((boost::
|
||||||
|
LessThanComparable<std::complex<float> >*)this)->boost::
|
||||||
|
LessThanComparable<std::complex<float> >::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> 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&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&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 © 2000</td>
|
||||||
<TR valign=top>
|
|
||||||
<TD nowrap>Copyright © 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>
|
||||||
|
@ -1,126 +1,125 @@
|
|||||||
<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&</tt> or <tt>const
|
|
||||||
T&</tt>. That means it would be a mistake to use <tt>T&</tt>
|
|
||||||
or <tt>const T&</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 <class T>
|
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
|
||||||
typedef input_iterator_archetype self;
|
verify that the chosen concepts <i>cover</i> the algorithm. That is, any
|
||||||
public:
|
possible user error should be caught by the concept checks and not let slip
|
||||||
typedef std::input_iterator_tag iterator_category;
|
through. Concept coverage can be verified through the use of <i>archetype
|
||||||
typedef T value_type;
|
classes</i>. An archetype class is an exact implementation of the interface
|
||||||
struct reference {
|
associated with a particular concept. The run-time behavior of the
|
||||||
operator const value_type&() const { return static_object<T>::get(); }
|
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
|
||||||
typedef const T* pointer;
|
to the component. If the program compiles then one can be sure that the
|
||||||
typedef std::ptrdiff_t difference_type;
|
concepts cover the component. The following code shows the archetype class
|
||||||
self& operator=(const self&) { return *this; }
|
for the <a href="http://www.sgi.com/tech/stl/InputIterator.html">Input
|
||||||
bool operator==(const self&) const { return true; }
|
Iterator</a> concept. Some care must be taken to ensure that the archetype
|
||||||
bool operator!=(const self&) const { return true; }
|
is an exact match to the concept. For example, the concept states that the
|
||||||
reference operator*() const { return reference(); }
|
return type of <tt>operator*()</tt> must be convertible to the value type.
|
||||||
self& operator++() { return *this; }
|
It does not state the more stringent requirement that the return type be
|
||||||
self operator++(int) { return *this; }
|
<tt>T&</tt> or <tt>const T&</tt>. That means it would be a mistake
|
||||||
|
to use <tt>T&</tt> or <tt>const T&</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 <class T>
|
||||||
|
class input_iterator_archetype
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef input_iterator_archetype self;
|
||||||
|
public:
|
||||||
|
typedef std::input_iterator_tag iterator_category;
|
||||||
|
typedef T value_type;
|
||||||
|
struct reference {
|
||||||
|
operator const value_type&() const { return static_object<T>::get(); }
|
||||||
};
|
};
|
||||||
|
typedef const T* pointer;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
self& operator=(const self&) { return *this; }
|
||||||
|
bool operator==(const self&) const { return true; }
|
||||||
|
bool operator!=(const self&) const { return true; }
|
||||||
|
reference operator*() const { return reference(); }
|
||||||
|
self& operator++() { 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<
|
||||||
{
|
sgi_assignable_archetype<> > ValueType;
|
||||||
typedef less_than_comparable_archetype<
|
random_access_iterator_archetype<ValueType> ri;
|
||||||
sgi_assignable_archetype<> > ValueType;
|
std::stable_sort(ri, ri);
|
||||||
random_access_iterator_archetype<ValueType> 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 © 2000</td>
|
||||||
<TR valign=top>
|
|
||||||
<TD nowrap>Copyright © 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>
|
||||||
|
@ -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 <class X>
|
||||||
RandomAccessIterator</a> concept. Typedefs can also be added to
|
struct InputIterator
|
||||||
enforce the associated types of the concept.
|
: Assignable<X>, EqualityComparable<X>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef std::iterator_traits<X> 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<difference_type>));
|
||||||
template <class Iter>
|
BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));
|
||||||
struct RandomAccessIteratorConcept
|
|
||||||
{
|
BOOST_CONCEPT_USAGE(InputIterator)
|
||||||
void constraints() {
|
{
|
||||||
function_requires< BidirectionalIteratorConcept<Iter> >();
|
X j(i); <font color=
|
||||||
function_requires< LessThanComparableConcept<Iter> >();
|
"green">// require copy construction</font>
|
||||||
function_requires< ConvertibleConcept<
|
same_type(*i++,v); <font color=
|
||||||
typename std::iterator_traits<Iter>::iterator_category,
|
"green">// require postincrement-dereference returning value_type</font>
|
||||||
std::random_access_iterator_tag> >();
|
X& x = ++j; <font color=
|
||||||
|
"green">// require preincrement returning X&</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<Iter>::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 <typename T>
|
||||||
|
void same_type(T const&, T const&);
|
||||||
|
};
|
||||||
|
</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& x = ++j; <font color=
|
||||||
|
"green">// require preincrement returning X&</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 © 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 © 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>
|
||||||
|
@ -13,7 +13,7 @@ namespace fake
|
|||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
template<typename RanIter>
|
template<typename RanIter>
|
||||||
BOOST_CONCEPT_WHERE(
|
BOOST_CONCEPT_REQUIRES(
|
||||||
((Mutable_RandomAccessIterator<RanIter>))
|
((Mutable_RandomAccessIterator<RanIter>))
|
||||||
((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>))
|
((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>))
|
||||||
|
|
||||||
|
@ -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&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&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 <class RandomAccessIterator>
|
template <class RandomAccessIterator>
|
||||||
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 = &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 <class Iter>
|
template <class Iter>
|
||||||
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 <class Iter>
|
template <class Iter>
|
||||||
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 <class Concept>
|
template <class Concept>
|
||||||
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 <type_var>::* func##type_var##concept)(); \
|
typedef void (ns::concept <type_var>::* func##type_var##concept)(); \
|
||||||
template <func##type_var##concept _Tp1> \
|
template <func##type_var##concept _Tp1> \
|
||||||
@ -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 © 2000</td>
|
||||||
<TR valign=top>
|
|
||||||
<TD nowrap>Copyright © 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>
|
||||||
|
@ -21,9 +21,20 @@ struct usage_requirements
|
|||||||
~usage_requirements() { ((Model*)0)->~Model(); }
|
~usage_requirements() { ((Model*)0)->~Model(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
# define BOOST_CONCEPT_USAGE(model) \
|
# if BOOST_WORKAROUND(__GNUC__, <= 3)
|
||||||
BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements<model>)); \
|
|
||||||
~model()
|
# define BOOST_CONCEPT_USAGE(model) \
|
||||||
|
model(); /* at least 2.96 and 3.4.3 both need this :( */ \
|
||||||
|
BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements<model>)); \
|
||||||
|
~model()
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
# define BOOST_CONCEPT_USAGE(model) \
|
||||||
|
BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements<model>)); \
|
||||||
|
~model()
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// Copyright David Abrahams 2006. Distributed under the Boost
|
// Copyright David Abrahams 2006. Distributed under the Boost
|
||||||
// Software License, Version 1.0. (See accompanying
|
// Software License, Version 1.0. (See accompanying
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
#ifndef BOOST_CONCEPT_WHERE_DWA2006430_HPP
|
#ifndef BOOST_CONCEPT_REQUIRES_DWA2006430_HPP
|
||||||
# define BOOST_CONCEPT_WHERE_DWA2006430_HPP
|
# define BOOST_CONCEPT_REQUIRES_DWA2006430_HPP
|
||||||
|
|
||||||
# include <boost/parameter/aux_/parenthesized_type.hpp>
|
# include <boost/parameter/aux_/parenthesized_type.hpp>
|
||||||
# include <boost/concept/assert.hpp>
|
# include <boost/concept/assert.hpp>
|
||||||
@ -12,7 +12,7 @@ namespace boost {
|
|||||||
|
|
||||||
// Template for use in handwritten assertions
|
// Template for use in handwritten assertions
|
||||||
template <class Model, class More>
|
template <class Model, class More>
|
||||||
struct where_ : More
|
struct requires_ : More
|
||||||
{
|
{
|
||||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||||
typedef typename More::type type;
|
typedef typename More::type type;
|
||||||
@ -23,41 +23,52 @@ struct where_ : More
|
|||||||
// Template for use by macros, where models must be wrapped in parens.
|
// Template for use by macros, where models must be wrapped in parens.
|
||||||
// This isn't in namespace detail to keep extra cruft out of resulting
|
// This isn't in namespace detail to keep extra cruft out of resulting
|
||||||
// error messages.
|
// error messages.
|
||||||
template <class ModelFn, class More>
|
template <class ModelFn>
|
||||||
struct _where_ : More
|
struct _requires_
|
||||||
{
|
{
|
||||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
enum { value = 0 };
|
||||||
typedef typename More::type type;
|
|
||||||
# endif
|
|
||||||
BOOST_CONCEPT_ASSERT_FN(ModelFn);
|
BOOST_CONCEPT_ASSERT_FN(ModelFn);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BOOST_CONCEPT_WHERE_OPEN(r,data,t) ::boost::_where_<void(*)t,
|
template <int check, class Result>
|
||||||
#define BOOST_CONCEPT_WHERE_CLOSE(r,data,t) >
|
struct Requires_ : ::boost::parameter::aux::unaryfunptr_arg_type<Result>
|
||||||
|
{
|
||||||
|
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||||
|
typedef typename ::boost::parameter::aux::unaryfunptr_arg_type<Result>::type type;
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define BOOST_CONCEPT_REQUIRES_(r,data,t) + (::boost::_requires_<void(*)t>::value)
|
||||||
|
|
||||||
#if defined(NDEBUG) || BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
#if defined(NDEBUG) || BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||||
|
|
||||||
# define BOOST_CONCEPT_WHERE(models, result) \
|
# define BOOST_CONCEPT_REQUIRES(models, result) \
|
||||||
typename ::boost::parameter::aux::unaryfunptr_arg_type<void(*)result>::type
|
typename ::boost::parameter::aux::unaryfunptr_arg_type<void(*)result>::type
|
||||||
|
|
||||||
#elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
#elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||||
|
|
||||||
// Same thing as below without the initial typename
|
// Same thing as below without the initial typename
|
||||||
# define BOOST_CONCEPT_WHERE(models, result) \
|
# define BOOST_CONCEPT_REQUIRES(models, result) \
|
||||||
BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_OPEN, ~, models) \
|
::boost::Requires_< \
|
||||||
|
(0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \
|
||||||
::boost::parameter::aux::unaryfunptr_arg_type<void(*)result> \
|
::boost::parameter::aux::unaryfunptr_arg_type<void(*)result> \
|
||||||
BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_CLOSE, ~, models)::type
|
>::type
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// This just ICEs on MSVC6 :(
|
// This just ICEs on MSVC6 :(
|
||||||
# define BOOST_CONCEPT_WHERE(models, result) \
|
# define BOOST_CONCEPT_REQUIRES(models, result) \
|
||||||
typename BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_OPEN, ~, models) \
|
typename ::boost::Requires_< \
|
||||||
::boost::parameter::aux::unaryfunptr_arg_type<void(*)result> \
|
(0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \
|
||||||
BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_CLOSE, ~, models)::type
|
void(*)result \
|
||||||
|
>::type
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// C++0x proposed syntax changed. This supports an older usage
|
||||||
|
#define BOOST_CONCEPT_WHERE(models,result) BOOST_CONCEPT_REQUIRES(models,result)
|
||||||
|
|
||||||
} // namespace boost::concept_check
|
} // namespace boost::concept_check
|
||||||
|
|
||||||
#endif // BOOST_CONCEPT_WHERE_DWA2006430_HPP
|
#endif // BOOST_CONCEPT_REQUIRES_DWA2006430_HPP
|
||||||
|
@ -62,9 +62,6 @@ namespace boost
|
|||||||
//
|
//
|
||||||
BOOST_concept(Integer, (T))
|
BOOST_concept(Integer, (T))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
Integer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(Integer)
|
BOOST_CONCEPT_USAGE(Integer)
|
||||||
{
|
{
|
||||||
x.error_type_must_be_an_integer_type();
|
x.error_type_must_be_an_integer_type();
|
||||||
@ -90,9 +87,6 @@ namespace boost
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
BOOST_concept(SignedInteger,(T)) {
|
BOOST_concept(SignedInteger,(T)) {
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
SignedInteger(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(SignedInteger) {
|
BOOST_CONCEPT_USAGE(SignedInteger) {
|
||||||
x.error_type_must_be_a_signed_integer_type();
|
x.error_type_must_be_a_signed_integer_type();
|
||||||
}
|
}
|
||||||
@ -110,9 +104,6 @@ namespace boost
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
BOOST_concept(UnsignedInteger,(T)) {
|
BOOST_concept(UnsignedInteger,(T)) {
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
UnsignedInteger(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(UnsignedInteger) {
|
BOOST_CONCEPT_USAGE(UnsignedInteger) {
|
||||||
x.error_type_must_be_an_unsigned_integer_type();
|
x.error_type_must_be_an_unsigned_integer_type();
|
||||||
}
|
}
|
||||||
@ -135,9 +126,6 @@ namespace boost
|
|||||||
|
|
||||||
BOOST_concept(DefaultConstructible,(TT))
|
BOOST_concept(DefaultConstructible,(TT))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
DefaultConstructible(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(DefaultConstructible) {
|
BOOST_CONCEPT_USAGE(DefaultConstructible) {
|
||||||
TT a; // require default constructor
|
TT a; // require default constructor
|
||||||
ignore_unused_variable_warning(a);
|
ignore_unused_variable_warning(a);
|
||||||
@ -146,13 +134,9 @@ namespace boost
|
|||||||
|
|
||||||
BOOST_concept(Assignable,(TT))
|
BOOST_concept(Assignable,(TT))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
Assignable(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BOOST_CONCEPT_USAGE(Assignable) {
|
BOOST_CONCEPT_USAGE(Assignable) {
|
||||||
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
|
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
|
||||||
a = a; // require assignment operator
|
a = a; // require assignment operator
|
||||||
#endif
|
#endif
|
||||||
const_constraints(a);
|
const_constraints(a);
|
||||||
}
|
}
|
||||||
@ -166,12 +150,9 @@ namespace boost
|
|||||||
TT a;
|
TT a;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
BOOST_concept(CopyConstructible,(TT))
|
BOOST_concept(CopyConstructible,(TT))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
CopyConstructible(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BOOST_CONCEPT_USAGE(CopyConstructible) {
|
BOOST_CONCEPT_USAGE(CopyConstructible) {
|
||||||
TT a(b); // require copy constructor
|
TT a(b); // require copy constructor
|
||||||
TT* ptr = &a; // require address of operator
|
TT* ptr = &a; // require address of operator
|
||||||
@ -191,10 +172,6 @@ namespace boost
|
|||||||
// The SGI STL version of Assignable requires copy constructor and operator=
|
// The SGI STL version of Assignable requires copy constructor and operator=
|
||||||
BOOST_concept(SGIAssignable,(TT))
|
BOOST_concept(SGIAssignable,(TT))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
SGIAssignable(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BOOST_CONCEPT_USAGE(SGIAssignable) {
|
BOOST_CONCEPT_USAGE(SGIAssignable) {
|
||||||
TT b(a);
|
TT b(a);
|
||||||
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
|
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
|
||||||
@ -216,9 +193,6 @@ namespace boost
|
|||||||
|
|
||||||
BOOST_concept(Convertible,(X)(Y))
|
BOOST_concept(Convertible,(X)(Y))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
Convertible(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(Convertible) {
|
BOOST_CONCEPT_USAGE(Convertible) {
|
||||||
Y y = x;
|
Y y = x;
|
||||||
ignore_unused_variable_warning(y);
|
ignore_unused_variable_warning(y);
|
||||||
@ -244,9 +218,6 @@ namespace boost
|
|||||||
|
|
||||||
BOOST_concept(EqualityComparable,(TT))
|
BOOST_concept(EqualityComparable,(TT))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
EqualityComparable(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(EqualityComparable) {
|
BOOST_CONCEPT_USAGE(EqualityComparable) {
|
||||||
require_boolean_expr(a == b);
|
require_boolean_expr(a == b);
|
||||||
require_boolean_expr(a != b);
|
require_boolean_expr(a != b);
|
||||||
@ -257,9 +228,6 @@ namespace boost
|
|||||||
|
|
||||||
BOOST_concept(LessThanComparable,(TT))
|
BOOST_concept(LessThanComparable,(TT))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
LessThanComparable(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(LessThanComparable) {
|
BOOST_CONCEPT_USAGE(LessThanComparable) {
|
||||||
require_boolean_expr(a < b);
|
require_boolean_expr(a < b);
|
||||||
}
|
}
|
||||||
@ -270,9 +238,6 @@ namespace boost
|
|||||||
// This is equivalent to SGI STL's LessThanComparable.
|
// This is equivalent to SGI STL's LessThanComparable.
|
||||||
BOOST_concept(Comparable,(TT))
|
BOOST_concept(Comparable,(TT))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
Comparable(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(Comparable) {
|
BOOST_CONCEPT_USAGE(Comparable) {
|
||||||
require_boolean_expr(a < b);
|
require_boolean_expr(a < b);
|
||||||
require_boolean_expr(a > b);
|
require_boolean_expr(a > b);
|
||||||
@ -283,18 +248,6 @@ namespace boost
|
|||||||
TT a, b;
|
TT a, b;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
|
|
||||||
BOOST_concept(NAME, (First)(Second)) \
|
|
||||||
{ \
|
|
||||||
NAME(); \
|
|
||||||
BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \
|
|
||||||
private: \
|
|
||||||
bool constraints_() { return a OP b; } \
|
|
||||||
First a; \
|
|
||||||
Second b; \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
|
#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
|
||||||
BOOST_concept(NAME, (First)(Second)) \
|
BOOST_concept(NAME, (First)(Second)) \
|
||||||
{ \
|
{ \
|
||||||
@ -304,20 +257,7 @@ namespace boost
|
|||||||
First a; \
|
First a; \
|
||||||
Second b; \
|
Second b; \
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \
|
|
||||||
BOOST_concept(NAME, (Ret)(First)(Second)) \
|
|
||||||
{ \
|
|
||||||
NAME(); \
|
|
||||||
BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \
|
|
||||||
private: \
|
|
||||||
Ret constraints_() { return a OP b; } \
|
|
||||||
First a; \
|
|
||||||
Second b; \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \
|
#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \
|
||||||
BOOST_concept(NAME, (Ret)(First)(Second)) \
|
BOOST_concept(NAME, (Ret)(First)(Second)) \
|
||||||
{ \
|
{ \
|
||||||
@ -327,7 +267,6 @@ namespace boost
|
|||||||
First a; \
|
First a; \
|
||||||
Second b; \
|
Second b; \
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp);
|
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp);
|
||||||
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp);
|
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp);
|
||||||
@ -347,9 +286,6 @@ namespace boost
|
|||||||
|
|
||||||
BOOST_concept(Generator,(Func)(Return))
|
BOOST_concept(Generator,(Func)(Return))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
Generator(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(Generator) { test(is_void<Return>()); }
|
BOOST_CONCEPT_USAGE(Generator) { test(is_void<Return>()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -370,9 +306,6 @@ namespace boost
|
|||||||
|
|
||||||
BOOST_concept(UnaryFunction,(Func)(Return)(Arg))
|
BOOST_concept(UnaryFunction,(Func)(Return)(Arg))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
UnaryFunction(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void<Return>()); }
|
BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void<Return>()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -394,9 +327,6 @@ namespace boost
|
|||||||
|
|
||||||
BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second))
|
BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
BinaryFunction(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void<Return>()); }
|
BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void<Return>()); }
|
||||||
private:
|
private:
|
||||||
void test(boost::mpl::false_)
|
void test(boost::mpl::false_)
|
||||||
@ -418,9 +348,6 @@ namespace boost
|
|||||||
|
|
||||||
BOOST_concept(UnaryPredicate,(Func)(Arg))
|
BOOST_concept(UnaryPredicate,(Func)(Arg))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
UnaryPredicate(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(UnaryPredicate) {
|
BOOST_CONCEPT_USAGE(UnaryPredicate) {
|
||||||
require_boolean_expr(f(arg)); // require operator() returning bool
|
require_boolean_expr(f(arg)); // require operator() returning bool
|
||||||
}
|
}
|
||||||
@ -431,9 +358,6 @@ namespace boost
|
|||||||
|
|
||||||
BOOST_concept(BinaryPredicate,(Func)(First)(Second))
|
BOOST_concept(BinaryPredicate,(Func)(First)(Second))
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(BinaryPredicate) {
|
BOOST_CONCEPT_USAGE(BinaryPredicate) {
|
||||||
require_boolean_expr(f(a, b)); // require operator() returning bool
|
require_boolean_expr(f(a, b)); // require operator() returning bool
|
||||||
}
|
}
|
||||||
@ -447,9 +371,6 @@ namespace boost
|
|||||||
BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second))
|
BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second))
|
||||||
: BinaryPredicate<Func, First, Second>
|
: BinaryPredicate<Func, First, Second>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
Const_BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(Const_BinaryPredicate) {
|
BOOST_CONCEPT_USAGE(Const_BinaryPredicate) {
|
||||||
const_constraints(f);
|
const_constraints(f);
|
||||||
}
|
}
|
||||||
@ -468,9 +389,6 @@ namespace boost
|
|||||||
{
|
{
|
||||||
typedef typename Func::result_type result_type;
|
typedef typename Func::result_type result_type;
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
AdaptableGenerator(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
BOOST_CONCEPT_USAGE(AdaptableGenerator)
|
BOOST_CONCEPT_USAGE(AdaptableGenerator)
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
|
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
|
||||||
@ -483,9 +401,6 @@ namespace boost
|
|||||||
typedef typename Func::argument_type argument_type;
|
typedef typename Func::argument_type argument_type;
|
||||||
typedef typename Func::result_type result_type;
|
typedef typename Func::result_type result_type;
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
AdaptableUnaryFunction(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~AdaptableUnaryFunction()
|
~AdaptableUnaryFunction()
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
|
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
|
||||||
@ -505,9 +420,6 @@ namespace boost
|
|||||||
typedef typename Func::second_argument_type second_argument_type;
|
typedef typename Func::second_argument_type second_argument_type;
|
||||||
typedef typename Func::result_type result_type;
|
typedef typename Func::result_type result_type;
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
AdaptableBinaryFunction(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~AdaptableBinaryFunction()
|
~AdaptableBinaryFunction()
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
|
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>));
|
||||||
@ -520,18 +432,12 @@ namespace boost
|
|||||||
: UnaryPredicate<Func, Arg>
|
: UnaryPredicate<Func, Arg>
|
||||||
, AdaptableUnaryFunction<Func, bool, Arg>
|
, AdaptableUnaryFunction<Func, bool, Arg>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
AdaptablePredicate(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second))
|
BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second))
|
||||||
: BinaryPredicate<Func, First, Second>
|
: BinaryPredicate<Func, First, Second>
|
||||||
, AdaptableBinaryFunction<Func, bool, First, Second>
|
, AdaptableBinaryFunction<Func, bool, First, Second>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
|
||||||
AdaptableBinaryPredicate(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@ -547,10 +453,7 @@ namespace boost
|
|||||||
typedef typename boost::detail::iterator_traits<TT>::pointer pointer;
|
typedef typename boost::detail::iterator_traits<TT>::pointer pointer;
|
||||||
typedef typename boost::detail::iterator_traits<TT>::iterator_category iterator_category;
|
typedef typename boost::detail::iterator_traits<TT>::iterator_category iterator_category;
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(InputIterator)
|
||||||
InputIterator(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~InputIterator()
|
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>));
|
BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>));
|
||||||
BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));
|
BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));
|
||||||
@ -567,10 +470,7 @@ namespace boost
|
|||||||
BOOST_concept(OutputIterator,(TT)(ValueT))
|
BOOST_concept(OutputIterator,(TT)(ValueT))
|
||||||
: Assignable<TT>
|
: Assignable<TT>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(OutputIterator) {
|
||||||
OutputIterator(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~OutputIterator() {
|
|
||||||
|
|
||||||
++i; // require preincrement operator
|
++i; // require preincrement operator
|
||||||
i++; // require postincrement operator
|
i++; // require postincrement operator
|
||||||
@ -584,10 +484,7 @@ namespace boost
|
|||||||
BOOST_concept(ForwardIterator,(TT))
|
BOOST_concept(ForwardIterator,(TT))
|
||||||
: InputIterator<TT>
|
: InputIterator<TT>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(ForwardIterator)
|
||||||
ForwardIterator(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~ForwardIterator()
|
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((Convertible<
|
BOOST_CONCEPT_ASSERT((Convertible<
|
||||||
BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category
|
BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category
|
||||||
@ -605,10 +502,7 @@ namespace boost
|
|||||||
BOOST_concept(Mutable_ForwardIterator,(TT))
|
BOOST_concept(Mutable_ForwardIterator,(TT))
|
||||||
: ForwardIterator<TT>
|
: ForwardIterator<TT>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(Mutable_ForwardIterator) {
|
||||||
Mutable_ForwardIterator(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~Mutable_ForwardIterator() {
|
|
||||||
*i++ = *i; // require postincrement and assignment
|
*i++ = *i; // require postincrement and assignment
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
@ -618,10 +512,7 @@ namespace boost
|
|||||||
BOOST_concept(BidirectionalIterator,(TT))
|
BOOST_concept(BidirectionalIterator,(TT))
|
||||||
: ForwardIterator<TT>
|
: ForwardIterator<TT>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(BidirectionalIterator)
|
||||||
BidirectionalIterator(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~BidirectionalIterator()
|
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((Convertible<
|
BOOST_CONCEPT_ASSERT((Convertible<
|
||||||
BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category
|
BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category
|
||||||
@ -639,10 +530,7 @@ namespace boost
|
|||||||
: BidirectionalIterator<TT>
|
: BidirectionalIterator<TT>
|
||||||
, Mutable_ForwardIterator<TT>
|
, Mutable_ForwardIterator<TT>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(Mutable_BidirectionalIterator)
|
||||||
Mutable_BidirectionalIterator(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~Mutable_BidirectionalIterator()
|
|
||||||
{
|
{
|
||||||
*i-- = *i; // require postdecrement and assignment
|
*i-- = *i; // require postdecrement and assignment
|
||||||
}
|
}
|
||||||
@ -654,10 +542,7 @@ namespace boost
|
|||||||
: BidirectionalIterator<TT>
|
: BidirectionalIterator<TT>
|
||||||
, Comparable<TT>
|
, Comparable<TT>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(RandomAccessIterator)
|
||||||
RandomAccessIterator(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~RandomAccessIterator()
|
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((Convertible<
|
BOOST_CONCEPT_ASSERT((Convertible<
|
||||||
BOOST_DEDUCED_TYPENAME BidirectionalIterator<TT>::iterator_category
|
BOOST_DEDUCED_TYPENAME BidirectionalIterator<TT>::iterator_category
|
||||||
@ -682,10 +567,7 @@ namespace boost
|
|||||||
: RandomAccessIterator<TT>
|
: RandomAccessIterator<TT>
|
||||||
, Mutable_BidirectionalIterator<TT>
|
, Mutable_BidirectionalIterator<TT>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(Mutable_RandomAccessIterator)
|
||||||
Mutable_RandomAccessIterator(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~Mutable_RandomAccessIterator()
|
|
||||||
{
|
{
|
||||||
i[n] = *i; // require element access and assignment
|
i[n] = *i; // require element access and assignment
|
||||||
}
|
}
|
||||||
@ -707,10 +589,7 @@ namespace boost
|
|||||||
typedef typename C::const_pointer const_pointer;
|
typedef typename C::const_pointer const_pointer;
|
||||||
typedef typename C::const_iterator const_iterator;
|
typedef typename C::const_iterator const_iterator;
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(Container)
|
||||||
Container(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~Container()
|
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((InputIterator<const_iterator>));
|
BOOST_CONCEPT_ASSERT((InputIterator<const_iterator>));
|
||||||
const_constraints(c);
|
const_constraints(c);
|
||||||
@ -737,10 +616,7 @@ namespace boost
|
|||||||
typedef typename C::iterator iterator;
|
typedef typename C::iterator iterator;
|
||||||
typedef typename C::pointer pointer;
|
typedef typename C::pointer pointer;
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(Mutable_Container)
|
||||||
Mutable_Container(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~Mutable_Container()
|
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((
|
BOOST_CONCEPT_ASSERT((
|
||||||
Assignable<typename Mutable_Container::value_type>));
|
Assignable<typename Mutable_Container::value_type>));
|
||||||
@ -760,10 +636,7 @@ namespace boost
|
|||||||
BOOST_concept(ForwardContainer,(C))
|
BOOST_concept(ForwardContainer,(C))
|
||||||
: Container<C>
|
: Container<C>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(ForwardContainer)
|
||||||
ForwardContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~ForwardContainer()
|
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((
|
BOOST_CONCEPT_ASSERT((
|
||||||
ForwardIterator<
|
ForwardIterator<
|
||||||
@ -776,10 +649,7 @@ namespace boost
|
|||||||
: ForwardContainer<C>
|
: ForwardContainer<C>
|
||||||
, Mutable_Container<C>
|
, Mutable_Container<C>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(Mutable_ForwardContainer)
|
||||||
Mutable_ForwardContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~Mutable_ForwardContainer()
|
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((
|
BOOST_CONCEPT_ASSERT((
|
||||||
Mutable_ForwardIterator<
|
Mutable_ForwardIterator<
|
||||||
@ -795,10 +665,7 @@ namespace boost
|
|||||||
C::const_reverse_iterator
|
C::const_reverse_iterator
|
||||||
const_reverse_iterator;
|
const_reverse_iterator;
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(ReversibleContainer)
|
||||||
ReversibleContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~ReversibleContainer()
|
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((
|
BOOST_CONCEPT_ASSERT((
|
||||||
BidirectionalIterator<
|
BidirectionalIterator<
|
||||||
@ -823,10 +690,7 @@ namespace boost
|
|||||||
{
|
{
|
||||||
typedef typename C::reverse_iterator reverse_iterator;
|
typedef typename C::reverse_iterator reverse_iterator;
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(Mutable_ReversibleContainer)
|
||||||
Mutable_ReversibleContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~Mutable_ReversibleContainer()
|
|
||||||
{
|
{
|
||||||
typedef typename Mutable_ForwardContainer<C>::iterator iterator;
|
typedef typename Mutable_ForwardContainer<C>::iterator iterator;
|
||||||
BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<iterator>));
|
BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<iterator>));
|
||||||
@ -845,10 +709,7 @@ namespace boost
|
|||||||
typedef typename C::size_type size_type;
|
typedef typename C::size_type size_type;
|
||||||
typedef typename C::const_reference const_reference;
|
typedef typename C::const_reference const_reference;
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(RandomAccessContainer)
|
||||||
RandomAccessContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~RandomAccessContainer()
|
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((
|
BOOST_CONCEPT_ASSERT((
|
||||||
RandomAccessIterator<
|
RandomAccessIterator<
|
||||||
@ -875,10 +736,7 @@ namespace boost
|
|||||||
private:
|
private:
|
||||||
typedef Mutable_RandomAccessContainer self;
|
typedef Mutable_RandomAccessContainer self;
|
||||||
public:
|
public:
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(Mutable_RandomAccessContainer)
|
||||||
Mutable_RandomAccessContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~Mutable_RandomAccessContainer()
|
|
||||||
{
|
{
|
||||||
BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::iterator>));
|
BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::iterator>));
|
||||||
BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::reverse_iterator>));
|
BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::reverse_iterator>));
|
||||||
@ -900,10 +758,7 @@ namespace boost
|
|||||||
// ... so why aren't we following the standard? --DWA
|
// ... so why aren't we following the standard? --DWA
|
||||||
, DefaultConstructible<S>
|
, DefaultConstructible<S>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(Sequence)
|
||||||
Sequence(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~Sequence()
|
|
||||||
{
|
{
|
||||||
S
|
S
|
||||||
c(n),
|
c(n),
|
||||||
@ -940,10 +795,7 @@ namespace boost
|
|||||||
BOOST_concept(FrontInsertionSequence,(S))
|
BOOST_concept(FrontInsertionSequence,(S))
|
||||||
: Sequence<S>
|
: Sequence<S>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(FrontInsertionSequence)
|
||||||
FrontInsertionSequence(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~FrontInsertionSequence()
|
|
||||||
{
|
{
|
||||||
c.push_front(t);
|
c.push_front(t);
|
||||||
c.pop_front();
|
c.pop_front();
|
||||||
@ -956,10 +808,7 @@ namespace boost
|
|||||||
BOOST_concept(BackInsertionSequence,(S))
|
BOOST_concept(BackInsertionSequence,(S))
|
||||||
: Sequence<S>
|
: Sequence<S>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(BackInsertionSequence)
|
||||||
BackInsertionSequence(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~BackInsertionSequence()
|
|
||||||
{
|
{
|
||||||
c.push_back(t);
|
c.push_back(t);
|
||||||
c.pop_back();
|
c.pop_back();
|
||||||
@ -986,10 +835,7 @@ namespace boost
|
|||||||
typedef typename C::value_compare value_compare;
|
typedef typename C::value_compare value_compare;
|
||||||
typedef typename C::iterator iterator;
|
typedef typename C::iterator iterator;
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(AssociativeContainer)
|
||||||
AssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~AssociativeContainer()
|
|
||||||
{
|
{
|
||||||
i = c.find(k);
|
i = c.find(k);
|
||||||
r = c.equal_range(k);
|
r = c.equal_range(k);
|
||||||
@ -1025,10 +871,7 @@ namespace boost
|
|||||||
BOOST_concept(UniqueAssociativeContainer,(C))
|
BOOST_concept(UniqueAssociativeContainer,(C))
|
||||||
: AssociativeContainer<C>
|
: AssociativeContainer<C>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(UniqueAssociativeContainer)
|
||||||
UniqueAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~UniqueAssociativeContainer()
|
|
||||||
{
|
{
|
||||||
C c(first, last);
|
C c(first, last);
|
||||||
|
|
||||||
@ -1046,10 +889,7 @@ namespace boost
|
|||||||
BOOST_concept(MultipleAssociativeContainer,(C))
|
BOOST_concept(MultipleAssociativeContainer,(C))
|
||||||
: AssociativeContainer<C>
|
: AssociativeContainer<C>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(MultipleAssociativeContainer)
|
||||||
MultipleAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~MultipleAssociativeContainer()
|
|
||||||
{
|
{
|
||||||
C c(first, last);
|
C c(first, last);
|
||||||
|
|
||||||
@ -1068,10 +908,7 @@ namespace boost
|
|||||||
BOOST_concept(SimpleAssociativeContainer,(C))
|
BOOST_concept(SimpleAssociativeContainer,(C))
|
||||||
: AssociativeContainer<C>
|
: AssociativeContainer<C>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(SimpleAssociativeContainer)
|
||||||
SimpleAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~SimpleAssociativeContainer()
|
|
||||||
{
|
{
|
||||||
typedef typename C::key_type key_type;
|
typedef typename C::key_type key_type;
|
||||||
typedef typename C::value_type value_type;
|
typedef typename C::value_type value_type;
|
||||||
@ -1082,10 +919,7 @@ namespace boost
|
|||||||
BOOST_concept(PairAssociativeContainer,(C))
|
BOOST_concept(PairAssociativeContainer,(C))
|
||||||
: AssociativeContainer<C>
|
: AssociativeContainer<C>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(PairAssociativeContainer)
|
||||||
PairAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~PairAssociativeContainer()
|
|
||||||
{
|
{
|
||||||
typedef typename C::key_type key_type;
|
typedef typename C::key_type key_type;
|
||||||
typedef typename C::value_type value_type;
|
typedef typename C::value_type value_type;
|
||||||
@ -1099,10 +933,7 @@ namespace boost
|
|||||||
: AssociativeContainer<C>
|
: AssociativeContainer<C>
|
||||||
, ReversibleContainer<C>
|
, ReversibleContainer<C>
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(__GNUC__, <= 3)
|
BOOST_CONCEPT_USAGE(SortedAssociativeContainer)
|
||||||
SortedAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :(
|
|
||||||
#endif
|
|
||||||
~SortedAssociativeContainer()
|
|
||||||
{
|
{
|
||||||
C
|
C
|
||||||
c(kc),
|
c(kc),
|
||||||
|
@ -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><</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 © 2000</td>
|
||||||
<TR valign=top>
|
|
||||||
<TD nowrap>Copyright © 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>
|
||||||
|
573
reference.htm
573
reference.htm
@ -1,308 +1,391 @@
|
|||||||
<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 <class Concept>
|
|
||||||
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>
|
<h3><a name="basic-concepts" id="basic-concepts">Basic Concept Checking
|
||||||
// Apply concept checks in class definitions.
|
Classes</a></h3>
|
||||||
BOOST_CLASS_REQUIRE(<i>type</i>, <i>namespace-of-concept</i>, <i>concept</i>);
|
<pre>
|
||||||
BOOST_CLASS_REQUIRE2(<i>type1</i>, <i>type2</i>, <i>namespace-of-concept</i>, <i>concept</i>);
|
#include "boost/concept_check.hpp"
|
||||||
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>);
|
template <class T>
|
||||||
|
struct Integer; // Is T a built-in integer type?
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct SignedInteger; // Is T a built-in signed integer type?
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct UnsignedInteger; // Is T a built-in unsigned integer type?
|
||||||
|
|
||||||
|
template <class X, class Y>
|
||||||
|
struct Convertible; // Is X convertible to Y?
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct <a href=
|
||||||
|
"../utility/Assignable.html">Assignable</a>; // Standard ref 23.1
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct SGI<a href=
|
||||||
|
"http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct <a href=
|
||||||
|
"../utility/CopyConstructible.html">CopyConstructible</a>; // Standard ref 20.1.3
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>; // Standard ref 20.1.1
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct <a href=
|
||||||
|
"../utility/LessThanComparable.html">LessThanComparable</a>; // Standard ref 20.1.2
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct Comparable; // The SGI STL <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a> concept
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Deprecated macros:
|
<h3><a name="iterator-concepts" id="iterator-concepts">Iterator Concept
|
||||||
|
Checking Classes</a></h3>
|
||||||
|
<pre>
|
||||||
|
template <class Iter>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>; // Standard ref 24.1.1 Table 72
|
||||||
|
|
||||||
<pre>
|
template <class Iter, class T>
|
||||||
// Apply concept checks in class definitions.
|
struct <a href=
|
||||||
BOOST_CLASS_REQUIRES(<i>type</i>, <i>concept</i>);
|
"http://www.sgi.com/tech/stl/OutputIterator.html">OutputIterator</a>; // Standard ref 24.1.2 Table 73
|
||||||
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>);
|
template <class Iter>
|
||||||
BOOST_CLASS_REQUIRES4(<i>type1</i>, <i>type2</i>, <i>type3</i>, <i>type4</i>, <i>concept</i>);
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>; // Standard ref 24.1.3 Table 74
|
||||||
|
|
||||||
|
template <class Iter>
|
||||||
|
struct Mutable_ForwardIterator;
|
||||||
|
|
||||||
|
template <class Iter>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>; // Standard ref 24.1.4 Table 75
|
||||||
|
|
||||||
|
template <class Iter>
|
||||||
|
struct Mutable_BidirectionalIterator;
|
||||||
|
|
||||||
|
template <class Iter>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>; // Standard ref 24.1.5 Table 76
|
||||||
|
|
||||||
|
template <class Iter>
|
||||||
|
struct Mutable_RandomAccessIterator;
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h3><a name="basic-concepts">Basic Concept Checking Classes</a></h3>
|
<h3><a name="function-object-concepts" id=
|
||||||
|
"function-object-concepts">Function Object Concept Checking
|
||||||
|
Classes</a></h3>
|
||||||
|
<pre>
|
||||||
|
#include "boost/concept_check.hpp"
|
||||||
|
|
||||||
<pre>
|
template <class Func, class Return>
|
||||||
template <class T>
|
struct <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>;
|
||||||
struct IntegerConcept; // Is T a built-in integer type?
|
|
||||||
|
|
||||||
template <class T>
|
template <class Func, class Return, class Arg>
|
||||||
struct SignedIntegerConcept; // Is T a built-in signed integer type?
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/UnaryFunction.html">UnaryFunction</a>;
|
||||||
|
|
||||||
template <class T>
|
template <class Func, class Return, class First, class Second>
|
||||||
struct UnsignedIntegerConcept; // Is T a built-in unsigned integer type?
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/BinaryFunction.html">BinaryFunction</a>;
|
||||||
|
|
||||||
template <class X, class Y>
|
template <class Func, class Arg>
|
||||||
struct ConvertibleConcept; // Is X convertible to Y?
|
struct Unary<a href=
|
||||||
|
"http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>;
|
||||||
|
|
||||||
template <class T>
|
template <class Func, class First, class Second>
|
||||||
struct <a href="../utility/Assignable.html">Assignable</a>Concept; // Standard ref 23.1
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>;
|
||||||
|
|
||||||
template <class T>
|
template <class Func, class First, class Second>
|
||||||
struct SGI<a href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>Concept;
|
struct Const_BinaryPredicate;
|
||||||
|
|
||||||
template <class T>
|
template <class Func, class Return>
|
||||||
struct <a
|
struct <a href=
|
||||||
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>Concept;
|
"http://www.sgi.com/tech/stl/AdaptableGenerator.html">AdaptableGenerator</a>;
|
||||||
|
|
||||||
template <class T>
|
template <class Func, class Return, class Arg>
|
||||||
struct <a href="../utility/CopyConstructible.html">CopyConstructible</a>Concept; // Standard ref 20.1.3
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>;
|
||||||
|
|
||||||
template <class T>
|
template <class Func, class First, class Second>
|
||||||
struct <a href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>Concept; // Standard ref 20.1.1
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>;
|
||||||
|
|
||||||
template <class T>
|
template <class Func, class Arg>
|
||||||
struct <a href="../utility/LessThanComparable.html">LessThanComparable</a>Concept; // Standard ref 20.1.2
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/AdaptablePredicate.html">AdaptablePredicate</a>;
|
||||||
|
|
||||||
template <class T>
|
template <class Func, class First, class Second>
|
||||||
struct ComparableConcept; // The SGI STL <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a> concept
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>;
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h3><a name="iterator-concepts">Iterator Concept Checking Classes</a></h3>
|
<h3><a name="container-concepts" id="container-concepts">Container Concept
|
||||||
|
Checking Classes</a></h3>
|
||||||
|
<pre>
|
||||||
|
#include "boost/concept_check.hpp"
|
||||||
|
|
||||||
<pre>
|
template <class C>
|
||||||
template <class Iter>
|
struct <a href=
|
||||||
struct <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>Concept; // Standard ref 24.1.1 Table 72
|
"http://www.sgi.com/tech/stl/Container.html">Container</a>; // Standard ref 23.1 Table 65
|
||||||
|
|
||||||
template <class Iter, class T>
|
template <class C>
|
||||||
struct <a href="http://www.sgi.com/tech/stl/OutputIterator.html">OutputIterator</a>Concept; // Standard ref 24.1.2 Table 73
|
struct Mutable_Container;
|
||||||
|
|
||||||
template <class Iter>
|
template <class C>
|
||||||
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/ForwardContainer.html">ForwardContainer</a>;
|
||||||
|
|
||||||
template <class Iter>
|
template <class C>
|
||||||
struct Mutable_ForwardIteratorConcept;
|
struct Mutable_ForwardContainer;
|
||||||
|
|
||||||
template <class Iter>
|
template <class C>
|
||||||
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/ReversibleContainer.html">ReversibleContainer</a>; // Standard ref 23.1 Table 66
|
||||||
|
|
||||||
template <class Iter>
|
template <class C>
|
||||||
struct Mutable_BidirectionalIteratorConcept;
|
struct Mutable_ReversibleContainer;
|
||||||
|
|
||||||
template <class Iter>
|
template <class C>
|
||||||
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/RandomAccessContainer.html">RandomAccessContainer</a>;
|
||||||
|
|
||||||
template <class Iter>
|
template <class C>
|
||||||
struct Mutable_RandomAccessIteratorConcept;
|
struct Mutable_RandomAccessContainer;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/Sequence.html">Sequence</a>; // Standard ref 23.1.1
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/BackInsertionSequence.html">BackInsertionSequence</a>;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/AssociativeContainer.html">AssociativeContainer</a>; // Standard ref 23.1.2 Table 69
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
struct <a href=
|
||||||
|
"http://www.sgi.com/tech/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>;
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h3><a name="function-object-concepts">Function Object Concept Checking Classes</a></h3>
|
<h3><a name="basic-archetype" id="basic-archetype">Basic Archetype
|
||||||
|
Classes</a></h3>
|
||||||
|
<pre>
|
||||||
|
#include "boost/concept_archetype.hpp"
|
||||||
|
|
||||||
<pre>
|
template <class T = int>
|
||||||
template <class Func, class Return>
|
class null_archetype; // A type that models no concepts.
|
||||||
struct <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>Concept;
|
|
||||||
|
|
||||||
template <class Func, class Return, class Arg>
|
template <class Base = null_archetype>
|
||||||
struct <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">UnaryFunction</a>Concept;
|
class default_constructible_archetype;
|
||||||
|
|
||||||
template <class Func, class Return, class First, class Second>
|
template <class Base = null_archetype>
|
||||||
struct <a href="http://www.sgi.com/tech/stl/BinaryFunction.html">BinaryFunction</a>Concept;
|
class assignable_archetype;
|
||||||
|
|
||||||
template <class Func, class Arg>
|
template <class Base = null_archetype>
|
||||||
struct Unary<a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>Concept;
|
class copy_constructible_archetype;
|
||||||
|
|
||||||
template <class Func, class First, class Second>
|
template <class Base = null_archetype>
|
||||||
struct <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>Concept;
|
class equality_comparable_archetype;
|
||||||
|
|
||||||
template <class Func, class First, class Second>
|
template <class T, class Base = null_archetype>
|
||||||
struct Const_BinaryPredicateConcept;
|
class convertible_to_archetype;
|
||||||
|
|
||||||
template <class Func, class Return>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/AdaptableGenerator.html">AdaptableGenerator</a>Concept;
|
|
||||||
|
|
||||||
template <class Func, class Return, class Arg>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>Concept;
|
|
||||||
|
|
||||||
template <class Func, class First, class Second>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a>Concept;
|
|
||||||
|
|
||||||
template <class Func, class Arg>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/AdaptablePredicate.html">AdaptablePredicate</a>Concept;
|
|
||||||
|
|
||||||
template <class Func, class First, class Second>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/AdaptableBinaryPredicate.html">AdaptableBinaryPredicate</a>Concept;
|
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h3><a name="container-concepts">Container Concept Checking Classes</a></h3>
|
<h3><a name="iterator-archetype" id="iterator-archetype">Iterator Archetype
|
||||||
|
Classes</a></h3>
|
||||||
|
<pre>
|
||||||
|
#include "boost/concept_archetype.hpp"
|
||||||
|
|
||||||
<pre>
|
template <class ValueType>
|
||||||
template <class C>
|
class trivial_iterator_archetype;
|
||||||
struct <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>Concept; // Standard ref 23.1 Table 65
|
|
||||||
|
|
||||||
template <class C>
|
template <class ValueType>
|
||||||
struct Mutable_ContainerConcept;
|
class mutable_trivial_iterator_archetype;
|
||||||
|
|
||||||
template <class C>
|
template <class ValueType>
|
||||||
struct <a href="http://www.sgi.com/tech/stl/ForwardContainer.html">ForwardContainer</a>Concept;
|
class input_iterator_archetype;
|
||||||
|
|
||||||
template <class C>
|
template <class ValueType>
|
||||||
struct Mutable_ForwardContainerConcept;
|
class forward_iterator_archetype;
|
||||||
|
|
||||||
template <class C>
|
template <class ValueType>
|
||||||
struct <a href="http://www.sgi.com/tech/stl/ReversibleContainer.html">ReversibleContainer</a>Concept; // Standard ref 23.1 Table 66
|
class bidirectional_iterator_archetype;
|
||||||
|
|
||||||
template <class C>
|
template <class ValueType>
|
||||||
struct Mutable_ReversibleContainerConcept;
|
class random_access_iterator_archetype;
|
||||||
|
|
||||||
template <class C>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/RandomAccessContainer.html">RandomAccessContainer</a>Concept;
|
|
||||||
|
|
||||||
template <class C>
|
|
||||||
struct Mutable_RandomAccessContainerConcept;
|
|
||||||
|
|
||||||
template <class C>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/Sequence.html">Sequence</a>Concept; // Standard ref 23.1.1
|
|
||||||
|
|
||||||
template <class C>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/FrontInsertionSequence.html">FrontInsertionSequence</a>Concept;
|
|
||||||
|
|
||||||
template <class C>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/BackInsertionSequence.html">BackInsertionSequence</a>Concept;
|
|
||||||
|
|
||||||
template <class C>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/AssociativeContainer.html">AssociativeContainer</a>Concept; // Standard ref 23.1.2 Table 69
|
|
||||||
|
|
||||||
template <class C>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html">UniqueAssociativeContainer</a>Concept;
|
|
||||||
|
|
||||||
template <class C>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/MultipleAssociativeContainer.html">MultipleAssociativeContainer</a>Concept;
|
|
||||||
|
|
||||||
template <class C>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/SimpleAssociativeContainer.html">SimpleAssociativeContainer</a>Concept;
|
|
||||||
|
|
||||||
template <class C>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/PairAssociativeContainer.html">PairAssociativeContainer</a>Concept;
|
|
||||||
|
|
||||||
template <class C>
|
|
||||||
struct <a href="http://www.sgi.com/tech/stl/SortedAssociativeContainer.html">SortedAssociativeContainer</a>Concept;
|
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<h3><a name="function-object-archetype" id=
|
||||||
|
"function-object-archetype">Function Object Archetype Classes</a></h3>
|
||||||
|
<pre>
|
||||||
|
#include "boost/concept_archetype.hpp"
|
||||||
|
|
||||||
<h3><a name="basic-archetype">Basic Archetype Classes</a></h3>
|
template <class Arg, class Return>
|
||||||
|
class unary_function_archetype;
|
||||||
|
|
||||||
<pre>
|
template <class Arg1, class Arg2, class Return>
|
||||||
template <class T = int>
|
class binary_function_archetype;
|
||||||
class null_archetype; // A type that models no concepts.
|
|
||||||
|
|
||||||
template <class Base = null_archetype>
|
template <class Arg>
|
||||||
class default_constructible_archetype;
|
class predicate_archetype;
|
||||||
|
|
||||||
template <class Base = null_archetype>
|
template <class Arg1, class Arg2>
|
||||||
class assignable_archetype;
|
class binary_predicate_archetype;
|
||||||
|
|
||||||
template <class Base = null_archetype>
|
|
||||||
class copy_constructible_archetype;
|
|
||||||
|
|
||||||
template <class Base = null_archetype>
|
|
||||||
class equality_comparable_archetype;
|
|
||||||
|
|
||||||
template <class T, class Base = null_archetype>
|
|
||||||
class convertible_to_archetype;
|
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h3><a name="iterator-archetype">Iterator Archetype Classes</a></h3>
|
<h3><a name="container-archetype" id="container-archetype">Container
|
||||||
|
Archetype Classes</a></h3>
|
||||||
<pre>
|
<pre>
|
||||||
template <class ValueType>
|
|
||||||
class trivial_iterator_archetype;
|
|
||||||
|
|
||||||
template <class ValueType>
|
|
||||||
class mutable_trivial_iterator_archetype;
|
|
||||||
|
|
||||||
template <class ValueType>
|
|
||||||
class input_iterator_archetype;
|
|
||||||
|
|
||||||
template <class ValueType>
|
|
||||||
class forward_iterator_archetype;
|
|
||||||
|
|
||||||
template <class ValueType>
|
|
||||||
class bidirectional_iterator_archetype;
|
|
||||||
|
|
||||||
template <class ValueType>
|
|
||||||
class random_access_iterator_archetype;
|
|
||||||
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h3><a name="function-object-archetype">Function Object Archetype Classes</a></h3>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
template <class Arg, class Return>
|
|
||||||
class unary_function_archetype;
|
|
||||||
|
|
||||||
template <class Arg1, class Arg2, class Return>
|
|
||||||
class binary_function_archetype;
|
|
||||||
|
|
||||||
template <class Arg>
|
|
||||||
class predicate_archetype;
|
|
||||||
|
|
||||||
template <class Arg1, class Arg2>
|
|
||||||
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 <class Concept>
|
||||||
<HR>
|
void function_requires();
|
||||||
<TABLE>
|
</pre>
|
||||||
<TR valign=top>
|
|
||||||
<TD nowrap>Copyright © 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 © 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>
|
||||||
|
@ -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 <class T>
|
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 <class T>
|
||||||
|
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<<em>X</em>></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 <class T>
|
||||||
|
void generic_library_function(T x)
|
||||||
|
{
|
||||||
|
BOOST_CONCEPT_ASSERT<strong>((</strong>EqualityComparable<T><strong>))</strong>;
|
||||||
|
<font color="green">// ...</font>
|
||||||
|
};
|
||||||
|
|
||||||
The <tt>function_requires()</tt> function can be used in function bodies
|
template <class It>
|
||||||
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<It><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 <class T>
|
<font color="green">//... </font>
|
||||||
void generic_library_function(T x)
|
};
|
||||||
{
|
|
||||||
function_requires< EqualityComparableConcept<T> >();
|
|
||||||
// ...
|
|
||||||
};
|
|
||||||
|
|
||||||
// In the user's code:
|
int main() {
|
||||||
class foo {
|
foo x;
|
||||||
//...
|
generic_library_function(x);
|
||||||
};
|
generic_library_class<std::vector<char>::iterator> 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 <class T>
|
algorithm might be declared as follows: class</p>
|
||||||
struct generic_library_class
|
<pre>
|
||||||
{
|
template<typename RanIter>
|
||||||
BOOST_CLASS_REQUIRE(T, boost, EqualityComparableConcept);
|
BOOST_CONCEPT_REQUIRES(
|
||||||
// ...
|
((Mutable_RandomAccessIterator<RanIter>))
|
||||||
};
|
((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>)),
|
||||||
|
(void)) <font color="green">// return type</font>
|
||||||
// In the user's code:
|
stable_sort(RanIter,RanIter);
|
||||||
class foo {
|
|
||||||
//...
|
|
||||||
};
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
generic_library_class<foo> 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 <class G, class Buffer, class BFSVisitor,
|
||||||
<a href="http://www.sgi.com/tech/stl/LessThanComparable.html">
|
class ColorMap>
|
||||||
LessThanComparable</a>, so we also use <tt>function_requires()</tt> to
|
BOOST_CONCEPT_REQUIRES(
|
||||||
check this.
|
((ReadWritePropertyMap<ColorMap, typename IncidenceGraph<G>::vertex_descriptor>)),
|
||||||
|
(void)) <font color="green">// return type</font>
|
||||||
<pre>
|
breadth_first_search(G& g,
|
||||||
template <class RandomAccessIter>
|
typename graph_traits<IncidenceGraph>::vertex_descriptor s,
|
||||||
void stable_sort(RandomAccessIter first, RandomAccessIter last)
|
Buffer& Q, BFSVisitor vis, ColorMap color)
|
||||||
{
|
{
|
||||||
function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
|
typedef typename IncidenceGraph<G>::vertex_descriptor Vertex;
|
||||||
typedef typename std::iterator_traits<RandomAccessIter>::value_type value_type;
|
...
|
||||||
function_requires< LessThanComparableConcept<value_type> >();
|
}
|
||||||
...
|
|
||||||
}
|
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<p>Although concept checks are designed for use by generic library
|
||||||
|
implementors, they can also be useful to end users. Sometimes one may not
|
||||||
<!-- There are a few places where the SGI STL documentation differs
|
be sure whether some type models a particular concept. The syntactic
|
||||||
from the corresponding requirements described in the C++ Standard. In
|
requirements, at least, can easily be checked by creating a small program
|
||||||
these cases we use the definition from the C++ Standard. -->
|
and using <tt>BOOST_CONCEPT_ASSERT</tt> with the type and concept in
|
||||||
|
question. For example:</p>
|
||||||
<p>
|
<pre>
|
||||||
Some concepts deal with more than one type. In this case the
|
<font color=
|
||||||
corresponding concept checking class will have multiple template
|
"green">// Make sure list<int> has bidirectional iterators.</font>
|
||||||
parameters. The following example shows how
|
BOOST_CONCEPT_ASSERT((BidirectionalIterator<std::list<int>::iterator>));
|
||||||
<tt>function_requires()</tt> is used with the <a
|
|
||||||
href="../property_map/ReadWritePropertyMap.html">ReadWritePropertyMap</a>
|
|
||||||
concept which takes two type parameters: a property map and the key
|
|
||||||
type for the map.
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
template <class IncidenceGraph, class Buffer, class BFSVisitor,
|
|
||||||
class ColorMap>
|
|
||||||
void breadth_first_search(IncidenceGraph& g,
|
|
||||||
typename graph_traits<IncidenceGraph>::vertex_descriptor s,
|
|
||||||
Buffer& Q, BFSVisitor vis, ColorMap color)
|
|
||||||
{
|
|
||||||
typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
|
|
||||||
function_requires< ReadWritePropertyMap<ColorMap, Vertex> >();
|
|
||||||
...
|
|
||||||
}
|
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<p><a href="./concept_check.htm">Prev: Concept Checking
|
||||||
|
Introduction</a><br />
|
||||||
|
<a href="./creating_concepts.htm">Next: Creating Concept Checking
|
||||||
|
Classes</a><br /></p>
|
||||||
|
<hr />
|
||||||
|
|
||||||
As an example of using <tt>BOOST_CLASS_REQUIRE</tt> we look at a concept
|
<table>
|
||||||
check that could be added to <tt>std::vector</tt>. One requirement
|
<tr valign="top">
|
||||||
that is placed on the element type is that it must be <a
|
<td nowrap="nowrap">Copyright © 2000</td>
|
||||||
href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>.
|
|
||||||
We can check this by inserting
|
|
||||||
<tt>class_requires<AssignableConcept<T> ></tt> at the top
|
|
||||||
of the definition for <tt>std::vector</tt>.
|
|
||||||
|
|
||||||
<pre>
|
<td><a href="../../people/jeremy_siek.htm">Jeremy Siek</a>(<a href=
|
||||||
namespace std {
|
"mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>) Andrew
|
||||||
template <class T>
|
Lumsdaine(<a href="mailto:lums@osl.iu.edu">lums@osl.iu.edu</a>), 2007
|
||||||
struct vector {
|
<a href="mailto:dave@boost-consulting.com">David Abrahams</a>.</td>
|
||||||
BOOST_CLASS_REQUIRE(T, boost, AssignableConcept);
|
</tr>
|
||||||
...
|
</table>
|
||||||
};
|
</body>
|
||||||
}
|
</html>
|
||||||
</pre>
|
|
||||||
|
|
||||||
|
|
||||||
Although the concept checks are designed for use by generic library
|
|
||||||
implementors, they can also be useful to end users. Sometimes one may
|
|
||||||
not be sure whether some type models a particular concept. This can
|
|
||||||
easily be checked by creating a small program and using
|
|
||||||
<tt>function_requires()</tt> with the type and concept in question.
|
|
||||||
The file <a
|
|
||||||
href="./stl_concept_check.cpp"><tt>stl_concept_checks.cpp</tt></a>
|
|
||||||
gives and example of applying the concept checks to STL containers.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="./concept_check.htm">Prev: Concept Checking Introduction</a> <br>
|
|
||||||
<a href="./creating_concepts.htm">Next: Creating Concept Checking Classes</a>
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<HR>
|
|
||||||
<TABLE>
|
|
||||||
<TR valign=top>
|
|
||||||
<TD nowrap>Copyright © 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>
|
|
||||||
|
Reference in New Issue
Block a user