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