1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
As a prelude before actually looking at how concepts are defined it is noted
that concept names, like class names, type names, function names, and variable
names should suggest their purposes. Don't name a concept `tt(Constraint)' or
`tt(Concept)', but use names like `tt(Addable)' and `tt(HasValueType)'.
Concepts are templates. They start with a template header (the
template headers shown in the examples define a single template type
parameter, but multiple template parameters are also used).
In the previous section we used the concept tt(Addable). Here is how it can
be defined:
verb( template <typename Type>
concept Addable =
requires(Type lh, Type rh)
{
lh + rh;
};)
The concept's template header is followed by the keyword tt(concept), the
concept's name, and the assignment operator. Following the assignment operator
hi(requires)em(requirement specifications) are provided.
Semicolons end concept definitions. This concept uses a
em(simple requirement) (cf. section ref(REQSIMPLE)) indicating that
tt(operator+) must have been defined for tt(Addable) templates' types.
Requirements come in many forms. A very simple form consists of just a
tt(bool) value, which is sometimes useful when developing a concept. Such a
concept looks like this:
verb(template <typename Type>
concept IsTrue =
true;
)
But in most situations tt(requires) specifications are used. They resemble
function definitions having parameter lists optionally defining variables of
the types that specified in the concept's template header and compound
statements specifying requirements.
Concepts are em(never) instantiated. They are used compile-time to verify that
template types satisfy the imposed requirements. Thus there's no need
to use refererences in parameter lists of tt(requires) specifications. The
concept tt(Addable) simply uses
verb( requires(Type lh, Type rh))
and there's no need to specify
verb( requires(Type const &lh, Type const &rh))
(That is, usually there is no need for this. In section ref(REQNEST) we
encounter a situation where a more specific parameter definition might be
appropriate.)
Here are two examples of templates using tt(concept Addable). The first example
uses tt(Addable) instead of tt(typedef) when specifying the template header, the
second example appends the concept specification to the template header
itself:
verbinsert(-s4 //requires examples/requires.cc)
Template declarations using concepts are specified accordingly. Simply replace
the function template's body by a semicolon.
Concepts may also be defined by extending or combining existing concepts.
em(Nesting) concepts is covered in section ref(REQNEST).
Although concepts are templates, they cannot be specialized. If a concept
should recognize specializations then these specializations must be handled by
the concepts' definitions. Section ref(REQCOMP) for an illustration
|