Concepts Jyrki Katajainen (University of Copenhagen) Sources: • Perform web-search with term ConceptC ++ Course home page: http://www.diku.dk/forskning/ performance-engineering/ Generic-programming/ c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (1)
Polymorphism The word polymorphism means “the ability to have many forms”. Parametric polymorphism: C ++ templates Inclusion polymorphism: C ++ virtual functions Overloading: C ++ function overloading including partial specializa- tion Coercion: C ++ built-in or user-defined conversion operators or con- structors to coercion. c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (2)
Bounded polymorphism Bounded parametric polymorphism (or constrained genericity ) means that we can specify some constraints on type parameters. In C ++ , there is no way to specify constrains on type parameters, but many clever tricks and workarounds exist to support generic program- ming (including type mappings, tag dispatching, and SFINAE) There are two approaches to specify constraints on type parameters: 1. use as a type definition 2. list as a requirement template <cphstl::HasLess T> template <typename T> class point { requires // ... cphstl::HasLess<T> } class point { // ... } c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (3)
Problems with C ++ templates It is theoretically interesting that the template level of C ++ has the power of a Turing machine, but template meta-programming has its problems, particularly in the areas of • error reporting, • separate compilation, • debugging, • compilation speed, • code readability, • internal capacity and robust- • code maintainability, ness of compilers, and • portability. Most problems seem to be related to unbounded parametric poly- morphism. c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (4)
Compilation with g++ 1 #include <list> 2 #include <algorithm> 3 4 int main() { std::list<int> l; 5 std::sort(l.begin(), l.end()); 6 7 } kand-1> g++ -Wall -pedantic list-sort.c++ ← /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_algo.h: In ֓ function ’void�std::sort(_RandomAccessIterator,�_RandomAccessIterator)�[ ← ֓ with�_RandomAccessIterator�=�std::_List_iterator<int>]’: list-sort.c++:6: instantiated from here ← /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_algo.h:2713: ֓ error: no match for ’operator-’ in ’__last�-�__first’ /usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/bits/stl_algo.h: In ← ֓ function ’void�std::__final_insertion_sort(_RandomAccessIterator,� ← ֓ _RandomAccessIterator)�[with�_RandomAccessIterator�=�std::_List_iterator< ← ֓ int>]’: ... c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (5)
Compilation with conceptg++ 1 #include <list> 2 #include <algorithm> 3 4 int main() { std::list<int> l; 5 std::sort(l.begin(), l.end()); 6 7 } kand-1> conceptg++ -Wall -pedantic list-sort.c++ list-sort.c++: In function ’int�main()’: list-sort.c++:6: error: no matching function for call to ’sort(std:: ← ֓ _List_iterator<int>,�std::_List_iterator<int>)’ /usr/local/lib/gcc/i686-pc-linux-gnu/4.3.0/../../../../include/c++/4.3.0/ ← ֓ bits/stl_algo.h:2872: note: candidates are: void std::sort(_Iter, _Iter) ← ֓ [with _Iter = std::_List_iterator<int>] <where clause> list-sort.c++:6: note: no concept map for requirement ’std:: ← ֓ MutableRandomAccessIterator<std::_List_iterator<int>�>’ Unfortunately, the compilation is noticeably slower. Why? c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (6)
Four definitions “A concept is a set of requirements [on types] bundled together under a single name.” [Gregor 2006] “a type system—called concepts —for C ++ types and values that can be used for template arguments” [Reis & Stroustrup 2006] “concepts are compile-time predicates on types and values (e.g. in- tegral constant values). They can be combined with the usual logical operators ( and , or , not ).” [Reis & Stroustrup 2006] “Everybody’s first idea for [defining the predicates] is to specify a concept as a set of operations” [Reis & Stroustrup 2006] c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (7)
Requirements on parameters “The fundamental problem is that a template definition is not (by itself) a good specification of its requirements on its parameters. We need to make those requirements explicit and less ad hoc than the expression of an algorithm. ’Concepts’ are such requirements.” [Reis & Stroustrup 2006] Requirements for classes Requirements for functions • typedefs defined • parameter types • member functions defined • return types • attributes defined (cannot be • functions relied on expressed in Concept C ++ ) • types relied on • member classes defined c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (8)
Old style template <typename R> void stable_sort(R a, R z); Requires • R is a model of random-access iterator. • R is mutable. • R ’s value type is strict-weakly comparable. . . . Complexity Let N be z − a . The worst-case behaviour is O ( N (lg N ) 2 ) if no auxiliary memory is available, and O ( N lg N ) if a large enough auxiliary memory buffer is available. c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (9)
New style #include <concepts> // defines std concepts #include <iterator> // defines std iterator concepts template <std::MutableRandomAccessIterator R> requires std::LessThanComparable<R::value_type> void stable_sort(R a, R z); Preconditions dynamic_assert(z - a ≥ 0); Postconditions dynamic_assert(chpstl::is_sorted(a, z)); . . . Complexity requirements Let N be z − a .. . . O ( N (lg N ) 2 ). . . c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (10)
Signatures Signatures permit conversions of the argument and result types. auto concept HasLess<typename T, typename U = T> { bool operator<(T const&, U const&); }; The declaration of operator< requires the existence of a < operator— either built in, as a free function, or as a member function—that can be passed two values convertible to type T and that returns a value convertible to bool . The auto preceding concept means that this is an implicit concept, for which we never have to write a model declaration. c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (11)
Default implementations Default implementations serve the same purpose as the comparison operators in the std::rel ops namespace, but without its problems. 1 auto concept LessThanComparable<typename T> : HasLess<T> { 2 bool operator>(T const& a, T const& b) { 3 return b < a; } 4 5 bool operator ≤ (T const& a, T const& b) { 6 return !(b < a); 7 } 8 9 bool operator ≥ (T const& a, T const& b) { 10 return !(a < b); 11 } 12 13 ... 14 }; c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (12)
Semantic concepts 1 auto concept LessThanComparable<typename T> : HasLess<T> { 2 ... axiom Transitivity(T a, T b, T c) { axiom Consistency(T a, T b) { 17 3 (a > b) ≡ (b < a); if (a < b && b < c) 18 4 (a < c) ≡ true; (a ≤ b) ≡ !(b < a); 19 5 } (a ≥ b) ≡ !(a < b); 20 6 } 21 7 axiom TransitivityOf ≡ (T a, T b, T c) { 22 8 if (!(a < b) && !(b < a) && axiom Irreflexivity(T a) { 23 9 !(b < c) && !(c < b)) (a < a) ≡ false; 24 10 (!(a < c) && !(c < a)) ≡ true; } 25 11 } 26 12 27 }; axiom Antisymmetry(T a, T b) { 13 if (a < b) 14 (b < a) ≡ false; 15 } 16 c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (13)
Associated types Associated types are represented as nested types within the concept; they replace traits and permit checking of template definitions. concept IteratorAssociatedTypes<typename X> { typename value_type = X::value_type; typename difference_type = X::difference_type; typename reference = X::reference; typename pointer = X::pointer; }; If a model does not specify a type definition for an associated type, then the model uses the default. c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (14)
Concept maps A model declaration illustrates how a set of types will model a particular concept. template <typename T> concept_map ForwardIterator<T*> { typedef T value_type; typedef std::size_t difference_type; typedef T& reference; typedef T* pointer; } Each model must meet all of the requirements in the concept. c � Performance Engineering Laboratory Generic programming and library development, 3 June 2008 (15)
Recommend
More recommend