158 lines
6.4 KiB
HTML
158 lines
6.4 KiB
HTML
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
|
|
||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
|
<!-- Copyright (c) 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" />
|
||
|
|
||
|
<title>Creating Concept Checking Classes</title>
|
||
|
<link rel="stylesheet" href="../../rst.css" type="text/css" />
|
||
|
</head>
|
||
|
|
||
|
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
||
|
"#FF0000">
|
||
|
<img src="../../boost.png" alt="C++ Boost" width="277" height=
|
||
|
"86" /><br clear="none" />
|
||
|
|
||
|
<h2><a name="creating-concept-checks" id="creating-concept-checks">Creating
|
||
|
Concept Checking Classes</a></h2>
|
||
|
|
||
|
<p>As an example of how to create a concept checking class template, we
|
||
|
look at how to create the corresponding checks for the <a href=
|
||
|
"http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a> concept.
|
||
|
The complete definition is here:</p>
|
||
|
<pre>
|
||
|
template <class X>
|
||
|
struct InputIterator
|
||
|
: 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;
|
||
|
|
||
|
BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>));
|
||
|
BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));
|
||
|
|
||
|
BOOST_CONCEPT_USAGE(InputIterator)
|
||
|
{
|
||
|
X j(i); <font color=
|
||
|
"green">// require copy construction</font>
|
||
|
same_type(*i++,v); <font color=
|
||
|
"green">// require postincrement-dereference returning value_type</font>
|
||
|
X& x = ++j; <font color=
|
||
|
"green">// require preincrement returning X&</font>
|
||
|
}
|
||
|
|
||
|
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=
|
||
|
"http://www.boost.org/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>
|
||
|
|
||
|
<p>Unfortunately, that code wouldn't have worked out so well, because it
|
||
|
unintentionally imposes the requirement that <code>X</code> and its value
|
||
|
type are both default-constructible. On the other hand, since instances of
|
||
|
the <code>InputIterator</code> template will never be constructed, the
|
||
|
compiler never has to check how its data members will be constructed (C++
|
||
|
Standard Section 14.7.1 9). For that reason you should <strong>always
|
||
|
declare values needed for usage patterns as data members</strong>.</p>
|
||
|
|
||
|
<p>These sorts of errors in concept definitions can be detected by the use
|
||
|
of <a href="concept_covering.htm">Concept Archetypes</a>, but it's always
|
||
|
better to avoid them pre-emptively.</p>
|
||
|
|
||
|
<h3>Similarity to Proposed C++0x Language Support for Concepts</h3>
|
||
|
|
||
|
<p>This library's syntaxes for concept refinement and for access of
|
||
|
associated types mirrors the corresponding <a href=
|
||
|
"http://www.generic-programming.org/languages/conceptcpp/">proposed</a>
|
||
|
syntaxes in C++0x. However, C++0x will use
|
||
|
“signatures” rather than usage patterns to
|
||
|
describe the valid operations on types participating in a concept, so when
|
||
|
converting your concept checking classes into language-supported concepts,
|
||
|
you'll need to translate your usage function into a series of
|
||
|
signatures.</p>
|
||
|
|
||
|
<p><a href="./concept_covering.htm">Next: Concept Covering and
|
||
|
Archetypes</a><br />
|
||
|
<a href="./using_concept_check.htm">Prev: Using Concept
|
||
|
Checks</a><br /></p>
|
||
|
<hr />
|
||
|
|
||
|
<table>
|
||
|
<tr valign="top">
|
||
|
<td nowrap="nowrap">Copyright © 2000</td>
|
||
|
|
||
|
<td><a href="http://www.boost.org/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>
|