C++ Concept Checking
by Jeremy Siek and Andrew Lumsdaine

Example 1
(a)
class Stack {
public:
   virtual void push(int x) = 0;
   virtual int pop() = 0;
};
void foo(Stack& x) {
   // use push() and pop()...
}


(b)
template <class Stack>
void bar(Stack& x) {
   // use push and pop...
}

Example 2:
#include <list>
#include <algorithm>
int main() {
   std::list<int> v;
   std::stable_sort(v.begin(), v.end());
   return 0;
}

Example 3:

boost/concept_check.hpp: In method 'void LessThanComparableConcept
   <_List_iterator<...> >::constraints()':
boost/concept_check.hpp:334: instantiated from 'RandomAccessIteratorConcept
   <_List_iterator<...> >::constraints()'
bad_error_eg.cpp:6: instantiated from 'stable_sort<_List_iterator
   <...> >(_List_iterator<...>,
   _List_iterator<...>)'
boost/concept_check.hpp:209: no match for '_List_iterator<...> &
   < _List_iterator<...> &'



Listing One

(a)
// In my library:
template <class T>
void some_function_template(T x)
{
   function_requires< EqualityComparableConcept<T> >();
   // ...
};
// In the user's code:
class foo {
//...
};
int main() {
   foo f;
   some_function_template(f);
   return 0;
}

(b)
// In my library:
template <class T>
struct some_class_template
{
   BOOST_CLASS_REQUIRES(T, EqualityComparableConcept);
   // ...
};
// In the user's code:
class foo {
   //...
};
int main() {
   some_class_template<foo> glc;
   // ...
   return 0;
}

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

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

Listing Three
template <class Iter>
struct RandomAccessIteratorConcept
{
   void constraints() {
      function_requires< BidirectionalIteratorConcept<Iter> >();
      function_requires< LessThanComparableConcept<Iter> >();
      function_requires< ConvertibleConcept<
         typename std::iterator_traits<Iter>::iterator_category,
         std::random_access_iterator_tag> >();
      i += n;
      i = i + n; i = n + i;
      i -= n;
      i = i - n;
      n = i - j;
      i[n];
   }
   Iter a, b;
   Iter i, j;
   typename std::iterator_traits<Iter>::difference_type n;
 };
}

Listing Four

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

Listing Five

template <class Iter>
struct RandomAccessIterator_concept
{
   void constraints()
   {
      i += n;
      ...
   }
   typename std::iterator_traits<RandomAccessIterator>
      ::difference_type n;
   Iter i;
   ...
};

Listing Six

(a)
template <class Iter>
void stable_sort(Iter first, Iter last)
{
   function_requires< RandomAccessIteratorConcept<Iter> >();
   ...
}

(b)
template <class Concept>
void function_requires()
{
   void (Concept::*x)() = BOOST_FPTR Concept::constraints;
   ignore_unused_variable_warning(x);
}

(c)
#define BOOST_CLASS_REQUIRES(type_var, concept) \
   typedef void (concept <type_var>::* func##type_var##concept)(); \
   template <func##type_var##concept _Tp1> \
   struct concept_checking_##type_var##concept { }; \
   typedef concept_checking_##type_var##concept< \
      BOOST_FPTR concept <type_var>::constraints> \
      concept_checking_typedef_##type_var##concept


Listing Seven 

template <class T>
struct input_proxy {
   operator const T&() {
      return static_object<T>::get(); // Get a reference without constructing
   }
};
template <class T>
class trivial_iterator_archetype
{
   typedef trivial_iterator_archetype self;
public:
   trivial_iterator_archetype() { }
   trivial_iterator_archetype(const self&) { }
   self& operator=(const self&) { return *this; }
   friend bool operator==(const self&, const self&) { return true; }
   friend bool operator!=(const self&, const self&) { return true; }
   input_proxy<T> operator*() { return input_proxy<T>(); }
};
namespace std {
   template <class T>
   struct iterator_traits< trivial_iterator_archetype<T> >
   {
      typedef T value_type;
   };
}

Listing Eight 
{
   typedef less_than_comparable_archetype<
      sgi_assignable_archetype<> > ValueType;
   random_access_iterator_archetype<ValueType> ri;
   std::stable_sort(ri, ri);
}







4

