This repository has been archived by the owner on Jan 6, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
different-types.bs
318 lines (261 loc) · 11.7 KB
/
different-types.bs
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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
<pre class="metadata">
Shortname: P2199
Revision: 0
Status: P
Group: WG21
Audience: LEWG
Title: Concepts to Differentiate Types
Editor: Isabella Muerte, imuerte@hey.com
No Abstract: no
Toggle Diffs: yes
Abstract: The differentiation of types is a commonly used constraint in C++.
Abstract: Typically, wording is copy pasted regarding this behavior, or shown
Abstract: only in exposition only helpers. Adding explicit definitions would
Abstract: reduce the need for multiple users to implement the same types.
</pre>
<style>
ins > * {background-color: #CCFFCC; text-decoration: underline;}
del > * {background-color: #FFCACA; text-decoration: line-through;}
tr.insert { background-color: #CCFFCC; text-decoration: underline; }
ins > clause {
justify-content: space-between;
display: flex;
}
</style>
# Revision History # {#changelog}
## Revision 1 ## {#r1}
Changed name of `similar_to` to `analagous_to` based on feedback from
LEWG(I) and various other folks reaching out about the use of *similar*
in [conv.qual]/3. This also avoids conflict with P2196.
## Revision 0 ## {#r0}
Initial Release. 🥳
# Motivation # {#motivation}
Within the standard library, there are multiple instances of phrases such as
"If *T* is the same type as *U*, the program is ill-formed", or *This function
does not participate in overload resolution unless the following contrainsts
are true*, followed by something like `is_same_v<remove_cvref_t<U>, type>`. It
would, honestly, be easier to express these with concepts. Furthermore, the
inversion of the `std::same_as` concept is much more common than `std::same_as`
itself when trying to constrain signatures of template types. Additionally, in
the realm of ranges, users tend to need to express that *analagous* types are ok
in some instances, while *distinct* (or *different*, see [[#feedback]] regarding
this phrase) are fairly common. In the author's work codebase, the inversion of
`std::same_as` appears about 20 times for each time where `std::same_as` is
used. While it is still early days regarding concepts, it would not be
surprising if other code bases had similar ratios, though most likely they are
not as extreme.
In the interest of symmetry with `same_as` and `different_from`, this paper
provides both `analagous_to` and `distinct_from`, although the wording found
below only redefines wording in terms of `different_from`, and `distinct_from`.
# Request for Feedback # {#feedback}
Currently, there is some ambiguity with the naming of `different_from` and
`distinct_from`. When something is *distinct*, it typically implies that it is
set apart and completely unique from something else. However, the direct
antonym of *same* in english is *different*. The author is fine with swapping
the definition of `different_from` and `distinct_from`, but will defer to
any consensus from LEWG or LWG if it is deemed necessary to swap their
definitions.
# Wording # {#wording}
The following wording is based off of the text found at <a
href=https://eel.is/c++draft>https://eel.is/c++draft</a> as of 2020-07-11.
The following is to be modified (according to a value as decided by LWG) in
17.3.2 <em>Header `<version>` synopsis</em>
**[version.syn]**, statement 2
<blockquote>
`#define __cpp_lib_concepts`
<del>`202002L`</del><ins>20����L</ins>
</blockquote>
The following is to be added to 18.3 <em>Header `<concepts>` synopsis</em>
**[concepts.syn]**
<blockquote>
<ins>
<em>// [concept.different], concept different_from</em><br>
`template <class T, class U>`<br>
 `concept different_from = ` <em>see below</em>`;`<br><br>
<em>// [concept.analagous], concept analagous_to</em><br>
`template <class T, class U>`<br>
 `concept analagous_to = ` <em>see below</em>`;`<br><br>
<em>// [concept.distinct], concept distinct_from</em><br>
`template <class T, class U>`<br>
 `concept distinct_from = ` <em>see below</em>`;`<br>
</ins>
</blockquote>
The following is to be added to 18.4 *Language-related concepts*
[**concepts.lang**]
<blockquote>
<ins>
<clause>18.4.� Concept `different_from` **[concept.different]**</clause>
`template <class T, class U>`<br>
 `concept different_from = not same_as<T, U>;`
<br>
<clause>18.4.� Concept `analagous_to` **[concept.analagous]**</clause>
`template <class T, class U>`<br>
  `concept analagous_to = same_as<remove_cvref_t<T>, remove_cvref_t<U>>;`
<br>
<clause>18.4.� Concept `distinct_from` **[concept.distinct]**</clause>
`template <class T, class U>`<br>
 `concept distinct_from = not analagous_to<T, U>;`
</ins>
</blockquote>
The following is to be modified in 20.6.3.1 *Constructors* **[optional.ctor]**,
statement 22
<blockquote>
*Constraints*: `is_constructible_v<T, U>` is `true`,
<del>`is_same_v<remove_cvref_t<U>`, `in_place_t>`</del><ins>`distinct_from<U,
in_place_t>`</ins>is <del>`false`</del><ins>`true`</ins>, and <del>
`is_same_v<remove_cvref_t<U>, optional>`</del><ins>`distinct_from<U,
optional>`</ins> is <del>`false`</del>.<ins>`true`</ins>
</blockquote>
The following is to be modified in 20.6.3.3 *Assignment* **[optional.assign]**,
statement 14
<blockquote>
*Constraints*: <del>`is_same_v<remove_cvref_t<U>, optional>`</del><ins>
`distinct_from<U, optional>`</ins>is<del>`false`</del><ins>`true`</ins>
</blockquote>
The following is to be modified in 20.7.3.3 *Assignment* **[variant.assign]**,
statement 12.1
<blockquote>
— <del>`is_same_v<remove_cvref_t<T>,
variant>`</del><ins>`distinct_from<T, variant>`</ins> is
<del>`false`</del><ins>`true`</ins>.
</blockquote>
The following is to be modified in 20.8.3.1 *Construction and destruction*
**[any.cons]**, statement 6
<blockquote>
*Constraints*: <del>`VT` is not the same type as
`any`</del><ins>`distinct_from<T, any>` is `true`</ins>
</blockquote>
The following is to be modified in 20.14.5.1 *Constructors and destructor*
**[refwrap.const]**, statement 2
<blockquote>
*Constraints*: The expression *FUN*`(declval<U>())` is well-formed and
<del>`is_same_v<remove_cvref_t<U>,
reference_wrapper>`</del><ins>`distinct_from<U, reference_wrapper>`</ins> is
<del>`false`</del><ins>`true`</ins>
</blockquote>
The following is to be modified from 21.2 *Character traits* **[char.traits]**,
statement 3
<blockquote>
To specialize those templates to generate a string, string view, or iostream
class to handle a particular character container type
([defns.character.container]) `C`, that and its related character traits class
`X` are passed as a pair of parameters to the string, string view, or iostream
template as parameters `charT` and `traits`. <del>If `X::char_type` is not the
same type as `C`, the program is ill-formed.</del><ins>If
`different_from<X::char_type, C>` is `true`, the program is ill-formed</ins>
</blockquote>
The following is to be modified from 21.3.2.1 *General requirements*
**[string.require]**, statement 3
<blockquote>
In every specialization `basic_string<charT, traits, Allocator>`, the type
`allocator_traits<Allocator>::value_type` shall name the same type as `charT`.
Every object of type `basic_string<charT, traits, Allocator>` uses an object of
type `Allocator` to allocate and free storage for the contained `charT` objects
as needed. The `Allocator` object used is obtained as described in
[container.requirements.general]. In every specialization `basic_string<charT,
traits, Allocator>`, the type `traits` shall mee the character traits
requirements ([char.traits]). [*Note:* The program is ill-formed if <del>
`traits::char_type` is not the same type as `charT`</del><ins>
`different_from<traits::char_type, charT>` is `true`</ins> --
*end note*]
</blockquote>
The following is to be modified from 21.4.2 <em>Class template
`basic_string_view`</em> **[string.view.template]**, statement 1
<blockquote> In every specialization `basic_string_view<charT, traits>`, the
type `traits` shall mee the character traits requirements ([char.traits]).
[*Note:* The program is ill-formed if <del> `traits::char_type` is not the same
type as `charT`</del><ins> `different_from<traits::char_type, charT>` is
`true`</ins> --
*end note*]
</blockquote>
The following is to be removed from 24.5.1 *Helper concepts*
[**range.utility.helpers**]
<blockquote>
<del>
`template<class T, class U>`<br>
[TAB]`concept not-same-as = // exposition only`<br>
[TAB]  `!same_as<remove_cvref_t<T>, remove_cvref_t<U>>;`
</del>
</blockquote>
The following is to be modified in 24.5.3 *Sub-ranges* [**range.subrange**]
<blockquote>
`template<class From, class To>`<br>
[TAB] `concept convertible-to-non-slicing = // exposition only`<br>
[TAB] [TAB] `convertible_to<From, To> &&`<br>
[TAB] [TAB] `!(is_pointer_v<decay_t<From>> &&`<br>
[TAB] [TAB]  `is_pointer_v<decay_t<To>> &&`<br>
<del>[TAB] [TAB]  `not-same-as<remove_pointer_t<decay_t<From>>,
remove_pointer_t<decay_t<To>>>);`</del><br> <ins>[TAB]
[TAB] `distinct_from<remove_pointer_t<decay_t<From>>,
remove_pointer_t<decay_t<To>>>);`</ins>
</blockquote>
The following is to be modified in 24.5.3.1 *Constructors and conversions*
[**range.subrange.ctor**]
<blockquote>
<del>`template<not-same-as<subrange> R>`</del><br>
<ins>`template<distinct_from<subrange> R>`</ins><br>
[TAB] `requires borrowed_range<R> &&`<br>
[TAB] [TAB] `convertible-to-non-slicing<iterator_t<R>, I> &&`<br>
[TAB] [TAB] `convertible_to<sentinel_t<R>, S>`<br>
`constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);`
</blockquote>
<blockquote>
<del>`template<not-same-as<subrange> PairLike>`</del><br>
<ins>`template<distinct_from<subrange> PairLike>`</ins><br>
[TAB] `requires pair-like-convertible-from<PairLike, const I&, const S&>`<br>
`constexpr operator PairLike() const;`
</blockquote>
The following is to be modified in 24.7.3.1 *Class template ref_view*
[**range.ref.view**]
Inside of statement 1
<blockquote>
<del>`template<not-same-as<ref_view> T>`</del><br>
<ins>`template<distinct_from<ref_view> T>`</ins><br>
[TAB] `requires /* see below */`<br>
`constexpr ref_view(T&& t);`
</blockquote>
At the definition preceeding statement 2
<blockquote>
<del>`template<not-same-as<ref_view> T>`</del><br>
<ins>`template<distinct_from<ref_view> T>`</ins><br>
[TAB] `requires /* see below */`<br>
`constexpr ref_view(T&& t);`
</blockquote>
The following is to be modified in 29.3.2 *Overview*
**[iostream.forward.overview]**, statement 6
<blockquote>
[*Note:* For each of the class tempaltes above, the program is ill-formed if
<del>`traits::char_type` is not the same type as
`charT`</del><ins>`different_from<traits::char_type, charT>` is `true`</ins>
([char.traits]) --
*end note*]
</blockquote>
The following is to be modified in 32.4.2.2 *Constructors*
**[thread.thread.constr]**, statement 3
<blockquote>
*Constraints*: <del>`remove_cvref_t<F>` is not the same type as
`thread`</del><ins>`distinct_from<F, thread>` is `true`</ins>
</blockquote>
The following is to be modified in 32.4.3.1 *Constructors, move, and
assignment*, statement 3
<blockquote>
*Constraints*: <del>`remove_cvref_t<F>` is not the same type as
`jthread`</del><ins>`distinct_from<F, jthread>` is `true`</ins>
</blockquote>
The following is to be modified in 32.9.10.1 *Member functions*
**[futures.task.members]**, statement 2
<blockquote>
*Constraints*: <del>`remove_cvref_t<F>` is not the same type as
`packaged_task<R(ArgTypes...)>`</del><ins>`distinct_from<F, packaged_task>` is
`true`</ins>
</blockquote>
The following is to be removed from the *Index of library concepts*
<p>
<del><em>not-same-as</em><strong>[range.utility.helpers]</strong></del>
</p>
The following is to be added to the *Index of library concepts*
<p>
<ins><code>different_from</code><strong>[concept.different]</strong></ins>,
<ins><code>analagous_to</code><strong>[concept.analagous]</strong></ins>,
<ins><code>distinct_from</code><strong>[concept.distinct]</strong></ins>
</p>