Alternatively the following syntax can be used: verb( template< typename Type> requires ComparableBySmaller Type const &min(Type const &x, Type const &y) { return y < x ? y : x; } ) The advantage of the former syntax is that it allows a list of requirements, e.g., linebreak() tt(ComparableBySmaller, Ordered). Moreover, these requirements may be combined using the logical negation (! (tt(not))) and conjunction (&& (tt(and))) operators. To define a concept hi(concept: definition) the following syntax will be provided: verb( auto concept ComparableBySmaller { bool operator<(Type, Type); } ) This concept specifies that a type supporting an tt(operator<) accepting two tt(Type) objects and returning a tt(bool) is a tt(ComparableBySmaller) type. Note that this therefore becomes an implied characteristic of an actual type. Any type defining this operator by implication also becomes a tt(ComparableBySmaller) type. Any such type may therefore be used to instantiate a template with that requires the tt(ComparableBySmaller) concept. The C++ standard introduces emi(axiom)em(s) as a feature of concepts. Axioms can be used to define properties of concepts, such as their associativity. Here is a preliminary example of how an axiom could be used in the definition of a concept: verb( concept Semigroup< typename Op, typename Type> : CopyConstructible { Type operator()(Op, Type, Type); axiom Associativity(Op op, Type x, Type y, Type z) { op(x, op(y, z)) == op(op(x, y), z); } }; ) As remarked, concepts and axioms are currently still unavailable in the tt(g++) compiler. It is likely that this section will be vastly expanded by the time the compiler has fully implemented the C2a standard. Concepts, axioms and related constructs may eventually even be covered in a separate chapter. COMMENT( ================================================================= The operator need not be a free-function; it could be a member function of the type T. Concepts can involve multiple objects as well. For example, concepts can express that a type is convertible from one type to another: auto concept Convertible< typename T, typename U> { operator U(const T&); } In order to use this in a template, it must use a generalized form of concept usage: template< typename U, typename T> requires Convertible U convert(const T& t) { return t; } Concepts may be composed. For example, given a concept named Regular: concept InputIterator< typename Iter, typename Value> { requires Regular; Value operator*(const Iter&); Iter& operator++(Iter&); Iter operator++(Iter&, int); } The first template parameter to the InputIterator concept must conform to the Regular concept. Concepts can also be derived from one another, like inheritance. Like in class inheritance, types that meet the requirements of the derived concept also meet the requirements of the base concept. It is defined as per class derivation: concept ForwardIterator< typename Iter, typename Value> : InputIterator { //Add other requirements here. } Typenames can also be associated with a concept. These impose the requirement that, in templates that use those concepts, these typenames are available: concept InputIterator< typename Iter> { typename value_type; typename reference; typename pointer; typename difference_type; requires Regular; requires Convertible; reference operator*(const Iter&); // dereference Iter& operator++(Iter&); // pre-increment Iter operator++(Iter&, int); // post-increment //... } Concept maps allow types to be explicitly bound to a concept. They also allow types to, where possible, adopt the syntax of a concept without changing the definition of the type. As an example: concept_map InputIterator { using value_type = char; using reference = char &; using pointer = char *; using difference_type = std::ptrdiff_t; }; This map fills in the required typenames for the InputIterator concept when applied to char* types. As an added degree of flexibility, concept maps themselves can be templated. The above example can be extended to all pointer types: template< typename T> concept_map InputIterator { using value_type = T; using reference = T &; using pointer = T *; using difference_type = std::ptrdiff_t; }; Further, concept maps can act as mini-types, with function definitions and other constructs commonly associated with classes: concept Stack< typename X> { typename value_type; void push(X&, const value_type&); void pop(X&); value_type top(const X&); bool empty(const X&); }; template< typename T> concept_map Stack > { using value_type = T; void push(std::vector& v, const T& x) { v.push_back(x); } void pop(std::vector& v) { v.pop_back(); } T top(const std::vector& v) { return v.back(); } bool empty(const std::vector& v) { return v.empty(); } }; This concept map allows templates that take types that implement the concept Stack to take a std::vector, remapping the function calls directly to the std::vector calls. Ultimately, this allows a pre-existing object to be converted, without touching the definition of the object, into an interface that a template function can utilize. Finally, it should be noted that some requirements can be checked using static assertions. These can verify some requirements that templates need, but are really aimed at a different problem. ================================================================ Compilers are allowed, but not required, to take advantage of the semantics specified by axioms to perform optimizations that possibly have side-effects on the observable behavior of the program, which are typically prohibited (with few exceptions such as copy constructor elision). In the above example, compilers may reassociate nested calls to operator() of type Op on several values of type Type provided that there is a concept map for types Op and Type to the concept Semigroup. Axioms can also assist in software verification, software testing, and other program analyses and transformations. =========================================================== END)