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 void bar(Stack& x) { // use push and pop... } Example 2: #include #include int main() { std::list 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 void some_function_template(T x) { function_requires< EqualityComparableConcept >(); // ... }; // In the user's code: class foo { //... }; int main() { foo f; some_function_template(f); return 0; } (b) // In my library: template struct some_class_template { BOOST_CLASS_REQUIRES(T, EqualityComparableConcept); // ... }; // In the user's code: class foo { //... }; int main() { some_class_template glc; // ... return 0; } Listing Two (a) template void stable_sort(RandomAccessIter first, RandomAccessIter last) { function_requires< RandomAccessIteratorConcept >(); typedef typename std::iterator_traits:: value_type value_type; function_requires< LessThanComparableConcept >(); ... } (b) namespace std { template struct vector { BOOST_CLASS_REQUIRES(T, AssignableConcept); ... }; } Listing Three template struct RandomAccessIteratorConcept { void constraints() { function_requires< BidirectionalIteratorConcept >(); function_requires< LessThanComparableConcept >(); function_requires< ConvertibleConcept< typename std::iterator_traits::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::difference_type n; }; } Listing Four template void stable_sort_constraints(RandomAccessIterator i) { typename std::iterator_traits ::difference_type n; i += n; // exercise the requirements for RandomAccessIterator ... } template void stable_sort(RandomAccessIterator first, RandomAccessIterator last) { typedef void (*fptr_type)(RandomAccessIterator); fptr_type x = &stable_sort_constraints; ... } Listing Five template struct RandomAccessIterator_concept { void constraints() { i += n; ... } typename std::iterator_traits ::difference_type n; Iter i; ... }; Listing Six (a) template void stable_sort(Iter first, Iter last) { function_requires< RandomAccessIteratorConcept >(); ... } (b) template 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 ::* func##type_var##concept)(); \ template \ struct concept_checking_##type_var##concept { }; \ typedef concept_checking_##type_var##concept< \ BOOST_FPTR concept ::constraints> \ concept_checking_typedef_##type_var##concept Listing Seven template struct input_proxy { operator const T&() { return static_object::get(); // Get a reference without constructing } }; template 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 operator*() { return input_proxy(); } }; namespace std { template struct iterator_traits< trivial_iterator_archetype > { typedef T value_type; }; } Listing Eight { typedef less_than_comparable_archetype< sgi_assignable_archetype<> > ValueType; random_access_iterator_archetype ri; std::stable_sort(ri, ri); } 4