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
|
In the following example a nested class, not depending on a template
parameter, is defined inside a class template. The class template member
tt(nested) returns an object of this nested class. The example uses a
(deprecated) in-class member implementation. The reason for this will become
clear shortly.
verb(
template <typename T>
class Outer
{
public:
class Nested
{};
Nested nested() const
{
return Nested();
}
};
)
The above example compiles flawlessly. Inside the class tt(Outer) there is
no ambiguity with respect to the meaning of tt(nested)'s return type.
However, following good practices inline and template members should be
implemented below their class interfaces (see section ref(DEFINLINE)). So we
remove the implementation from the interface and put it below the interface:
verb(
template <typename T>
class Outer
{
public:
class Nested
{};
Nested nested() const;
};
template <typename T>
Outer<T>::Nested Outer<T>::nested() const
{
return Nested();
}
)
Suddenly the compiler refuses to compile the tt(nested) member, producing an
error message like
quote(
em(error:)
emi(expected constructor, destructor, or type conversion) em(before
'Outer').)
Now that the implementation is moved out of the interface the return type
(i.e., tt(Outer<T>::Nested)) refers to a type defined by tt(Outer<T>) rather
than to a member of tt(Outer<T>).
Here, too, tt(typename) must be used. The general rule being: the keyword
tt(typename) must be used whenever a type is referred to that is a em(subtype)
of a type that itself depends on a template type parameter.
hi(template: subtypes inside templates)
hi(class template: subtype vs. static members)
Writing tt(typename) in front of tt(Outer<T>::Nested) removes the
compilation error. Thus, the correct implementation of the function
tt(nested) becomes:
verb(
template <typename T>
typename Outer<T>::Nested Outer<T>::nested() const
{
return Nested();
}
)
|