File: typename.yo

package info (click to toggle)
c%2B%2B-annotations 13.02.02-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,576 kB
  • sloc: cpp: 25,297; makefile: 1,523; ansic: 165; sh: 126; perl: 90; fortran: 27
file content (152 lines) | stat: -rw-r--r-- 5,591 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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
Until now the keyword tt(typename) has been used to indicate a template type
parameter. However, it is also used to
    hi(typename: disambiguating code)
 disambiguate code inside templates. Consider the following function template:
        verb(    template <typename Type>
    Type function(Type t)
    {
        Type::Ambiguous *ptr;

        return t + *ptr;
    })

When this code is processed by the compiler, it complains with an -at
first sight puzzling- error message like:
        verb(    4: error: 'ptr' was not declared in this scope)

The error message is puzzling as it was the programmer's intention to
declare a pointer to a type tt(Ambiguous) defined within the class template
tt(Type). But the compiler, confronted with tt(Type::Ambiguous) may interpret
the statement in various ways. Clearly it cannot inspect tt(Type) itself
trying to uncover tt(Type)'s true nature as tt(Type) is a template
type. Because of this tt(Type)'s actual definition isn't available yet.

    The compiler is confronted with two possibilities: either
tt(Type::Ambiguous) is a em(static member) of the as yet mysterious template
tt(Type), or it is a em(subtype) of tt(Type). As the standard
specifies that the compiler must assume the former, the statement
        verb(    Type::Ambiguous *ptr;)

is interpreted as a em(multiplication) of the static member
tt(Type::Ambiguous) and the (now undeclared) entity tt(ptr). The reason for
the error message should now be clear: in this context tt(ptr) is unknown.

    To disambiguate code in which an identifier refers to a
        hi(template: identifying subtypes)
        hi(class template: identifying subtypes)
        hi(typename: and template subtypes)
 subtype of a template type parameter the keyword tt(typename) must be
used. Accordingly, the above code is altered into:
        verb(    template <typename Type>
    Type function(Type t)
    {
        typename Type::Ambiguous *ptr;

        return t + *ptr;
    })

Classes fairly often define subtypes. When such subtypes appear inside
template definitions as subtypes of template type parameters the tt(typename)
keyword em(must) be used to identify them as subtypes. Example: a class
template tt(Handler) defines a tt(typename Container) as its template type
parameter. It also defines a data member storing the iterator returned by the
container's tt(begin) member. In addition tt(Handler) offers a constructor
accepting any container supporting a tt(begin) member.  tt(Handler)'s class
interface could then look like this:
        verb(    template <typename Container>
    class Handler
    {
        Container::const_iterator d_it;

        public:
            Handler(Container const &container)
            :
                d_it(container.begin())
            {}
    };)

What did  we have in mind when designing this class?
    itemization(
    it() The typename tt(Container) represents any container supporting
iterators.
    it() The container presumably supports a member tt(begin). The
initialization tt(d_it(container.begin())) clearly depends on the
template's type parameter, so it's only checked for basic syntactic
correctness.
    it() Likewise, the container presumably supports a em(subtype)
tt(const_iterator), defined in the class tt(Container).
    )
    The final consideration is an indication that tt(typename) is required. If
this is omitted and a tt(Handler) is instantiated the compiler produces a
peculiar compilation error:
        verb(    #include "handler.h"
    #include <vector>
    using namespace std;

    int main()
    {
        vector<int> vi;
        Handler<vector<int> > ph{ vi };
    }
    /*
        Reported error:

    handler.h:4: error: syntax error before `;' token
    */)

Clearly the line
        verb(    Container::const_iterator d_it;)

in the class tt(Handler) causes a problem. It is interpreted by the
compiler as a em(static member) instead of a subtype. The problem is
solved  using tt(typename):
        verb(    template <typename Container>
    class Handler
    {
        typename Container::const_iterator d_it;
        ...
    };)

An interesting illustration that the compiler indeed assumes tt(X::a) to
be a member tt(a) of the class tt(X) is provided by the error message we get
when we try to compile tt(main) using the following implementation of
tt(Handler)'s constructor:
        verb(    Handler(Container const &container)
    :
        d_it(container.begin())
    {
        size_t x = Container::ios_end;
    }
    /*
        Reported error:

        error: `ios_end' is not a member of type `std::vector<int,
                std::allocator<int> >'
    */)

Now consider what happens if the function template introduced at the
beginning of this section doesn't return a tt(Type) value, but a
tt(Type::Ambiguous) value. Again, a subtype of a template type is referred to,
and tt(typename) must be used:
        verb(    template <typename Type>
    typename Type::Ambiguous function(Type t)
    {
        return t.ambiguous();
    })

    tt(Typename)s can be embedded in using declarations. As is often the case,
this
        hi(template: embedded in using declarations)
reduces the complexities of declarations and definitions appearing
elsewhere. In the next example the type tt(Iterator) is defined as a subtype
of the template type tt(Container). tt(Iterator) may now be used without
requiring the use of the keyword tt(typename):
        verb(    template <typename Container>
    class Handler
    {
        using Iterator = Container::const_iterator;

        Iterator d_it;
        ...
    };)