Skip to content

Commit 583d925

Browse files
committed
Draft: Typedef Literacy.
1 parent 2429d84 commit 583d925

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
---
2+
layout: post
3+
title: "Typedef Literacy"
4+
modified:
5+
categories: programming
6+
excerpt: "Do you know how to read/write `typedef` properly?"
7+
tags: [c++, typedef, type-alias]
8+
date: 2016-05-12
9+
share: true
10+
draft: true
11+
---
12+
13+
__NOTE__: If you're writing >= C++11, reach for [type alias] rather than
14+
typedef declaration. The syntax matches what people naturally expect, and
15+
it also supports templated type aliases (i.e. alias template).
16+
17+
## Introduction
18+
19+
The typedef declaration provides a way to declare an alias for an existing
20+
type. For example, we can provide an alias for `int` called `integer` like so:
21+
22+
```c++
23+
typedef int integer;
24+
```
25+
26+
I imagine most people have seen such declarations, and it is fairly simple to
27+
read. In fact it's so simple that we may conclude that the syntax for `typedef`
28+
is:
29+
30+
```c++
31+
typedef <from> <to>;
32+
```
33+
34+
This syntax works for simple cases, but at some point we encounter a typedef
35+
declaration that doesn't quite meet our expectation:
36+
37+
```c++
38+
typedef int (*function_pointer)(float, double);
39+
```
40+
41+
This declares an alias for `int (*)(float, double)` (pointer to function) called
42+
`function_pointer`. This clearly isn't consistent with our earlier conclusion,
43+
since if it were, we would have seen the following instead:
44+
45+
```c++
46+
typedef int (*)(float, double) function_pointer;
47+
```
48+
49+
In an effort to keep the simple cases simple, people understandably start to
50+
treat this as a special case. Until they encounter another weird one.
51+
52+
```c++
53+
typedef int array[3];
54+
```
55+
56+
Fine. Yet another special case. But what about...
57+
58+
```c++
59+
typedef int integer, (*function_pointer)(int, double), array[3];
60+
```
61+
62+
Huh...? Is this even legal? --- Yes. Yes it is. (I'm not saying do it...)
63+
64+
How do we read these damn things?
65+
66+
## Correct Syntax
67+
68+
The core of the problem lies in the seemingly innocent and simple examples that
69+
lead us to naively assume the simple syntax. Here's the correct syntax for the
70+
typedef declaration according to [cppreference]:
71+
72+
```c++
73+
typedef type_declaration;
74+
```
75+
76+
The `type_declaration` after the `typedef` keyword is a simple declaration
77+
with some restrictions (e.g. cannot be declared `static`). In a variable
78+
declaration, the associated names are instances of the corresponding types.
79+
When the `typedef` keyword precedes the declaration, the associated names are
80+
aliases of the corresponding types.
81+
82+
For example, `array` in `int array[3];` is an instance of `int [3]`. When the
83+
`typedef` keyword appears before the declaration (i.e. `typedef int array[3];`),
84+
`array` becomes an alias for the type `int [3]`.
85+
86+
Thus, the task of reading a typedef declaration can be delegated to a reading
87+
a variable declaration then reinterpreting the names!
88+
89+
## Inaccurate Sources
90+
91+
Unfortunately, the source of the misunderstanding goes beyond us naively
92+
assuming the simple syntax.
93+
94+
- [Wikipedia article] enumerates a bunch of scenarios and makess it seem as
95+
if there are special cases, for function pointers for example.
96+
97+
> Function pointers are somewhat different than all other types because the
98+
> syntax does not follow the pattern `typedef <old type name> <new alias>;`.
99+
> Instead, the new alias for the type appears in the middle between the return
100+
> type (on the left) and the argument types (on the right). ...
101+
102+
* [Cplusplus tutorial] flat out incorrectly says:
103+
104+
> In C++, there are two syntaxes for creating such type aliases: The first,
105+
> inherited from the C language, uses the `typedef` keyword:
106+
>
107+
> `typedef existing_type new_type_name ;`
108+
>
109+
> where `existing_type` is any type, either fundamental or compound, and
110+
> `new_type_name` is an identifier with the new name given to the type.
111+
112+
## Conclusion
113+
114+
Hopefully I've helped in your ability to reason about `typedef` declarations.
115+
As I mentioned at the beginning of the post, reach for [type alias] instead if
116+
you're writing modern C++. What's interesting about `typedef` to me is that even
117+
though it successfully achieves the "make simple things simple" principle, the
118+
rule that one would naturally deduce from the simple case doesn't prepare you
119+
for the complex cases at all. I've also shown that the underlying rule is
120+
actually quite simple and consistent. It's an interesting result from a
121+
coherent design that managed to keep the simple cases simple.
122+
123+
## Standardese
124+
125+
The formal syntax can be found in §7 Declaration:
126+
127+
- §7 ¶1:
128+
129+
$$
130+
\begin{align}
131+
\textit{simp}&\textit{le-declaration:} \\
132+
&\textit{decl-specifier-seq} \space \textit{init-declarator-list}_{opt}\textit{;} \\
133+
&\textit{attribute-specifier-seq} \space \textit{decl-specifier-seq}\space\textit{init-declarator-list;} \\
134+
\end{align}
135+
$$
136+
137+
- §7 ¶9: If the _decl-specifier-seq_ contains the __typedef__ specifier, the
138+
declaration is called a _typedef declaration_ and the name of each
139+
_init-declarator_ is declared to be a _typedef-name_, synonymous with its
140+
associated type (7.1.3). ...
141+
142+
- §7.1.3 ¶1: Declarations containing the _decl-specifier_ __typedef__ declare
143+
identifiers that can be used later for naming fundamental (3.9.1) or compound
144+
(3.9.2) types. ...
145+
146+
[type alias]: http://en.cppreference.com/w/cpp/language/type_alias
147+
[cppreference]: http://en.cppreference.com/w/cpp/language/typedef
148+
[Wikipedia article]: https://en.wikipedia.org/wiki/Typedef
149+
[Cplusplus tutorial]: http://www.cplusplus.com/doc/tutorial/other_data_types/

0 commit comments

Comments
 (0)