## Using Concept Checks

For each concept there is a concept checking class which can be used to make sure that a given type (or set of types) models the concept. The Boost Concept Checking Library (BCCL) includes concept checking classes for all of the concepts used in the C++ standard library and a few more. The Reference 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 graph concepts and property map concepts. Also, whenever anyone 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 Creating Concept Checking Classes.

An example of a concept checking class from the BCCL is the `EqualityComparableConcept` class. The class corresponds to the EqualityComparable requirements described in 20.1.1 of the C++ Standard, and to the EqualityComparable concept documented in the SGI STL.

      template <class T>
      struct EqualityComparableConcept;

The template argument `T` will the type to be checked. That is, the purpose of `EqualityComparableConcept` is to make sure that the template argument given for `T` models the EqualityComparable concept.

Each concept checking class has a member function named `constraints()` 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 `constraints()` function without actually executing the function. The Boost Concept Checking Library defines two utilities that make this easy: `function_requires()` and `BOOST_CLASS_REQUIRE`.

#### `function_requires()`

The `function_requires()` function can be used in function bodies and the `BOOST_CLASS_REQUIRE` macro can be used inside class bodies. The `function_requires()` function takes no arguments, but has a template parameter for the concept checking class. This means that the instantiated concept checking class must be given as an explicit template argument, as shown below.

      // In my library:
      template <class T>
      void generic_library_function(T x)
      {
        function_requires< EqualityComparableConcept<T> >();
        // ...
      };

      // In the user's code:
      class foo {
        //...
      };

      int main() {
        foo f;
        generic_library_function(f);
        return 0;
      }

#### `BOOST_CLASS_REQUIRE`

The `BOOST_CLASS_REQUIRE` macro can be used inside a class definition to check whether some type models a concept. Make sure that the arguments to this macro are simply identifiers. You may need to use typedef to get your types into this form.

      // In my library:
      template <class T>
      struct generic_library_class
      {
        BOOST_CLASS_REQUIRE(T, boost, EqualityComparableConcept);
        // ...
      };

      // In the user's code:
      class foo {
        //...
      };

      int main() {
        generic_library_class<foo> glc;
        // ...
        return 0;
      }

#### Example

Getting back to the earlier motivating example, one good application of concept checks would be to insert `function_requires()` at the top of `std::stable_sort()` to make sure the template parameter type models RandomAccessIterator. In addition, `std::stable_sort()` requires that the `value_type` of the iterators be LessThanComparable, so we also use `function_requires()` to check this.

      template <class RandomAccessIter>
      void stable_sort(RandomAccessIter first, RandomAccessIter last)
      {
        function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
        typedef typename std::iterator_traits<RandomAccessIter>::value_type value_type;
        function_requires< LessThanComparableConcept<value_type> >();
        ...
      }

Some concepts deal with more than one type. In this case the corresponding concept checking class will have multiple template parameters. The following example shows how `function_requires()` is used with the ReadWritePropertyMap concept which takes two type parameters: a property map and the key type for the map.

      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> >();
        ...
      }

As an example of using `BOOST_CLASS_REQUIRE` we look at a concept check that could be added to `std::vector`. One requirement that is placed on the element type is that it must be Assignable. We can check this by inserting `class_requires<AssignableConcept<T> >` at the top of the definition for `std::vector`.

      namespace std {
        template <class T>
        struct vector {
          BOOST_CLASS_REQUIRE(T, boost, AssignableConcept);
          ...
        };
      }

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 `function_requires()` with the type and concept in question. The file `stl_concept_checks.cpp` gives and example of applying the concept checks to STL containers.

Prev: Concept Checking Introduction
Next: Creating Concept Checking Classes

Copyright © 2000 | Jeremy Siek(jsiek@osl.iu.edu) Andrew Lumsdaine(lums@osl.iu.edu)