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
|
When defining members of class templates outside of their class interfaces the
members' template headers must match the class templates' template
headers. This is no different when using concepts.
In the following example the concept tt(Addable) is used when defining the
class template tt(Data). The class tt(Data) declares a
member tt(process), implemented below the class interface. Like the class of
which it is a member its header must also specify tt(Addable) (cf. section
ref(CONDEF)):
verb( template <Addable Type>
class Data
{
void process();
};
template <Addable Tp> // The concept must be specified,
void Data<Tp>::process() // but the formal type name
{ // doesn't have to be `Type'
...
})
Comparably, if a class template member function can only be used when a
constraint has been satisfied (but no additional constraints apply to other
class members), the class template's header can use tt(typename) and the
(additional) constraint can be tailored to members where applicable:
verb( template <typename Type> // generic template type parameter
class Data
{
void process() requires Addable<Type>; // additional requirement
};
template <typename X>
void Data<X>::process() requires Addable<X>
...)
Types of member templates themselves may also be constrained. Here too the
rule applies that the template headers of member implementations must match
those of their declarations:
verb( template <typename Type>
class Data
{
template <Addable Tp> // constraint applied to
void process(Tp par); // a member template
};
template <typename Type>
template <Addable Tp>
void Data<Type>::process(Tp par)
{
...
})
|