forked from boostorg/concept_check
changing directory name, and reorganizing docs
[SVN r8410]
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
|
||||
|
||||
<h2><a name="implementation">Implementation</a></h2>
|
||||
|
||||
Ideally we would like to catch, and indicate, the concept violation at
|
||||
the point of instantiation. As mentioned in D&E[<a
|
||||
href="bibliography.html#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:
|
||||
|
||||
<pre>
|
||||
template <class RandomAccessIterator>
|
||||
void stable_sort_constraints(RandomAccessIterator i) {
|
||||
typename std::iterator_traits<RandomAccessIterator>
|
||||
::difference_type n;
|
||||
i += n; // exercise the requirements for RandomAccessIterator
|
||||
...
|
||||
}
|
||||
template <class RandomAccessIterator>
|
||||
void stable_sort(RandomAccessIterator first, RandomAccessIterator last) {
|
||||
typedef void (*fptr_type)(RandomAccessIterator);
|
||||
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>
|
||||
template <class Iter>
|
||||
struct RandomAccessIterator_concept {
|
||||
void constraints() {
|
||||
i += n;
|
||||
...
|
||||
}
|
||||
typename std::iterator_traits<RandomAccessIterator>
|
||||
::difference_type n;
|
||||
Iter i;
|
||||
...
|
||||
};
|
||||
</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/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>.
|
||||
|
||||
<pre>
|
||||
template <class RandomAccessIter>
|
||||
void stable_sort(RandomAccessIter first, RandomAccessIter last)
|
||||
{
|
||||
function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
|
||||
...
|
||||
}
|
||||
</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>
|
||||
template <class Concept>
|
||||
void function_requires()
|
||||
{
|
||||
void (Concept::*x)() = BOOST_FPTR Concept::constraints;
|
||||
ignore_unused_variable_warning(x);
|
||||
}
|
||||
</pre>
|
||||
|
||||
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
|
||||
class definition (whereas <tt>function_requires()</tt> can only be
|
||||
used inside of a function body). <tt>class_requires</tt> 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.
|
||||
|
||||
<pre>
|
||||
template <class Concept>
|
||||
class class_requires
|
||||
{
|
||||
typedef void (Concept::* function_pointer)();
|
||||
|
||||
template <function_pointer Fptr>
|
||||
struct dummy_struct { };
|
||||
public:
|
||||
typedef dummy_struct< BOOST_FPTR Concept::constraints > check;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<tt>class_requires</tt> was not used in the implementation of the
|
||||
Boost Concept Checking Library concept checks because several
|
||||
compilers do not implement template parameters of function pointer
|
||||
type.
|
||||
|
||||
Reference in New Issue
Block a user