File: returnnested.yo

package info (click to toggle)
c%2B%2B-annotations 12.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 13,044 kB
  • sloc: cpp: 24,337; makefile: 1,517; ansic: 165; sh: 121; perl: 90
file content (72 lines) | stat: -rw-r--r-- 2,762 bytes parent folder | download | duplicates (2)
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
68
69
70
71
72
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 shortly
becomes clear.
        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. Fortunately,
it also suggests a solution in its error message:
    verb(    error: need `typename' before `Outer<T>::Nested' because 
           `Outer<T>' is a dependent scope
     Outer<T>::Nested Outer<T>::nested() const
     ~~~~~~~~)

Now that the implementation has been 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>), and so tt(typename) must once again
be used. 

    A general rule for using tt(typename) can be formulated: 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)
    When using the inline implementation no such dependency is used as the
function's return type is simply tt(Nested). When implementing the function
outside of the class interface (which should be considered `good practice')
then a specification of the class defining tt(Nested) must be provided for the
function's return type. So it becomes tt(Outer<T>::Nested) which clearly is a
type depending on a template type parameter.

    Like before, 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();
    })