-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathswitch-enum-scope.html
245 lines (210 loc) · 9.17 KB
/
switch-enum-scope.html
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">
<title>Unqualified enumerators in case labels</title>
<style type="text/css">
body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }
p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }
code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
border: 1px solid #E1E28E; }
p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
padding-right: 1ex; }
.attribute dd { margin-left: 0em; }
blockquote.std { color: #000000; background-color: #F1F1F1;
border: 1px solid #D1D1D1;
padding-left: 0.5em; padding-right: 0.5em; }
blockquote.std del { text-decoration: line-through;
color: #000000; background-color: #FFEBFF;
border: 1px solid #ECD7EC; }
blockquote.std ins { text-decoration: underline;
color: #000000; background-color: #C8FFC8; }
table { border: 1px solid black; border-spacing: 0px;
margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
padding-left: 0.8em; border: none; }
table.frontmatter { border: 0; margin: 0; }
ul.dash { list-style-type: none; }
ul.dash li:before { content: '\2014'; margin-left: -1em }
span.highlight { background-color: #FFFF00; }
</style>
<script type="text/javascript" src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js"></script>
</head>
<body>
<h1>Unqualified enumerators in case labels</h1>
<table class="frontmatter" border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" width="619">
<tr>
<td align="left" valign="top">Document number:</td>
<td>P0284R0</td>
</tr>
<tr>
<td align="left" valign="top">Date:</td>
<td>2016-02-14</td>
</tr>
<tr>
<td align="left" valign="top">Project:</td>
<td>Programming Language C++, Evolution Working Group</td>
</tr>
<tr>
<td align="left" valign="top">Reply-to:</td>
<td>James Touton <<a href="mailto:[email protected]">[email protected]</a>></td>
</tr>
</table>
<h2><a id="TableOfContents">Table of Contents</a></h2>
<ol>
<li><a href="#TableOfContents">Table of Contents</a></li>
<li><a href="#Introduction">Introduction</a></li>
<li><a href="#MotivationAndScope">Motivation and Scope</a></li>
<li><a href="#ImpactOnTheStandard">Impact On the Standard</a></li>
<li><a href="#DesignDecisions">Design Decisions</a></li>
<li><a href="#TechnicalSpecifications">Technical Specifications</a></li>
<li><a href="#Wording">Wording</a></li>
</ol>
<h2><a id="Introduction">Introduction</a></h2>
<p>This paper proposes allowing unqualified name lookup to find (scoped or unscoped) enumerators when the type of the condition of the enclosing switch statement is an enumeration.
Example:</p>
<pre class="example">
<code class="prettyprint">enum class Foo
{
Bar,
Baz
};
namespace N
{
enum Alehouse
{
Pub,
Bar,
Tavern
}
}
int f(Foo foo, N::Alehouse h)
{
switch (foo)
{
case Bar: // <em>ok: finds Foo::Bar</em>
return 1;
}
switch (h)
{
case Bar: // <em>ok: finds N::Alehouse::Bar</em>
return 2;
}
return -1;
}</code>
</pre>
<h2><a id="MotivationAndScope">Motivation and Scope</a></h2>
<p>This proposal aims to reduce unnecessary verbosity.
Switch statements and enumerations are very frequently used together.
A case label's constant expression must be convertible to the (adjusted) type of the switch statement's condition;
when the condition is an enumeration, each case label's constant expression must be convertible to that enumeration.
When an enumerator belonging to that enumeration appears in a case label, it therefore seems unnecessarily pedantic to require the programmer to explicitly qualify the enumerator name when the enumerator is not presently visible in the enclosing scope.</p>
<pre class="example">
<code class="prettyprint">enum class Color
{
Black, Blue, Green, Cyan, Red, Magenta, Yellow, White
};
int color_code(Color color)
{
// <em>Under current rules, every enumerator here must</em>
// <em>be prefixed with the enumeration name even though</em>
// <em>no other values are possible without explicit</em>
// <em>conversions.</em>
switch (color)
{
case <span class="highlight">Color</span>::Black:
return 0x000000;
case <span class="highlight">Color</span>::Blue:
return 0x0000FF;
case <span class="highlight">Color</span>::Green:
return 0x00FF00;
case <span class="highlight">Color</span>::Cyan:
return 0x00FFFF;
case <span class="highlight">Color</span>::Red:
return 0xFF0000;
case <span class="highlight">Color</span>::Magenta:
return 0xFF00FF;
case <span class="highlight">Color</span>::Yellow:
return 0xFFFF00;
case <span class="highlight">Color</span>::White:
return 0xFFFFFF;
}
}</code>
</pre>
<h2><a id="ImpactOnTheStandard">Impact On the Standard</a></h2>
<p>This proposal extends the visibility of enumerators to cover case labels when the condition of the associated switch statement is of the type of the enumeration.</p>
<p>Some pathological examples of existing code could change in meaning.
In order for this to happen, an existing case label would need to reference a named constant in an enclosing namespace (outside of the function definition) that has the same name as an enumerator and a value distinct from that enumerator.
This should be extremely rare, and may actually be indicative of a bug in existing code.</p>
<h2><a id="DesignDecisions">Design Decisions</a></h2>
<h3>Name hiding</h3>
<p>This proposal extends the potential scope of enumerators to cover case labels in switch statements where the codition of the switch statement has the same type as the enumeration.
This carries with it new potential for name collisions when the name of an enumerator already carries different meaning in the scope of the case label.
This paper takes the position that an enumerator name appearing in a case label is more likely to refer to the enumerator than to another entity, but gives deference to function-local entities that can't be referenced any other way.
An enumerator name is therefore allowed to hide entities at class and namespace scope, but is itself hidden by entities at function and block scope.</p>
<p>Example:</p>
<pre class="example">
<code class="prettyprint">enum class Color
{
Black, Blue, Green, Cyan, Red, Magenta, Yellow, White
};
constexpr int Yellow = 42;
int color_code(Color color)
{
int Black = 27;
switch (color)
{
case Black: // <em>error: function-local Black, not Color::Black</em>
return 0x000000;
case Yellow: // <em>ok: Color::Yellow</em>
return 0xFFFF00;
// <em>...</em>
}
return -1;
}</code>
</pre>
<h2><a id="TechnicalSpecifications">Technical Specifications</a></h2>
<ul>
<li>When a case label appears in a switch statement and the adjusted type of the switch statement's condition is an enumeration, the enumerators belonging to that enumeration are visible in case label's <var>constant-expression</var>.</li>
<li>Enumerators made visible in a case label hide competing names at class scope and namespace scope.</li>
</ul>
<h2><a id="Wording">Wording</a></h2>
<p>All modifications are presented relative to N4567.</p>
<p>Add the following paragraph to §3.3.1 [basic.scope.declarative]:</p>
<blockquote class="std">
<p><ins>The potential scope of an enumerator additionally includes some case labels as described in 6.4.2.</ins></p>
</blockquote>
<p>Insert the following paragraph after §3.3.10 [basic.scope.hiding] paragraph 4:</p>
<blockquote class="std">
<p><ins>Within the <var>constant-expression</var> of a case label where the potential scope of an enumerator has been extended to include the <var>constant-expression</var> (6.4.2), a name declared at class or namespace scope can be hidden by the enumerator, and the enumerator can be hidden by a name declared at function or block scope.</ins></p>
</blockquote>
<p>Insert the following paragraph after §6.4.2 [stmt.switch] paragraph 2:</p>
<blockquote class="std">
<p><ins>When the condition is of enumeration type, the potential scope of the enumerators of the enumeration is extended to include the <var>constant-expression</var>s of the <code>switch</code> statement's associated <code>case</code> labels.
[ <i>Example:</i></ins></p>
<pre class="example">
<ins><code>enum class color { red, yellow, green, blue };
bool reddish(color col)
{
switch (col)
{
case red: // <em>ok: color::red</em>
case yellow: // <em>ok: color::blue</em>
return true;
default:
return false;
}
}</code></ins>
</pre>
<p><ins>—<i>end example</i> ]</ins></p>
</blockquote>
</body></html>