Skip to content

Commit f89163e

Browse files
committed
feat(named_req): Swappable, CopyAssignable
1 parent 3d7d464 commit f89163e

File tree

5 files changed

+260
-11
lines changed

5 files changed

+260
-11
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
title: "C++ named requirements: CopyAssignable"
3+
cppdoc:
4+
revision:
5+
since: C++11
6+
---
7+
8+
import { DR, DRList } from "@components/defect-report";
9+
import { Desc, DescList } from "@components/desc-list";
10+
import Missing from "@components/Missing.astro";
11+
import { Revision, RevisionBlock } from "@components/revision";
12+
13+
Specifies that an instance of the type can be copy-assigned from an lvalue expression.
14+
15+
16+
## Requirements
17+
18+
The type T satisfies _CopyAssignable_ if
19+
20+
- The type T satisfies _MoveAssignable_, and
21+
22+
Given
23+
24+
- `t`, a modifiable lvalue expression of type `T`,
25+
- `v`, an lvalue expression of type `T` or `const T` or an rvalue expression of type `const T`.
26+
27+
The following expressions must be valid and have their specified effects.
28+
29+
|Expression| Return type | Return value |Post-conditions|
30+
|---|---|---|---|
31+
|`t=v`| `T&` | `t` |The value of t is equivalent to the value of v.<br/> The value of v is unchanged. |
32+
33+
## See also
34+
35+
<DescList>
36+
<Desc kind="class template">
37+
<Fragment slot="item">
38+
<RevisionBlock noborder since="C++11">
39+
<Missing> `std::is_copy_assignable` </Missing>
40+
</RevisionBlock>
41+
<RevisionBlock noborder since="C++11">
42+
<Missing> `std::is_trivially_copy_assignable` </Missing>
43+
</RevisionBlock>
44+
<RevisionBlock noborder since="C++11">
45+
<Missing> `std::is_nothrow_copy_assignable` </Missing>
46+
</RevisionBlock>
47+
</Fragment>
48+
checks if a type has a copy assignment operator
49+
</Desc>
50+
<Desc kind="concept">
51+
<Fragment slot="item">
52+
<RevisionBlock noborder since="C++20">
53+
<Missing> `assignable_from` </Missing>
54+
</RevisionBlock>
55+
</Fragment>
56+
specifies that an object of a type can be default constructed
57+
</Desc>
58+
</DescList>
59+

src/content/docs/cpp/language/named_req/DefaultConstructible.mdx renamed to src/content/docs/cpp/language/named_req/default-constructible.mdx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ cppdoc:
77

88
import { DR, DRList } from "@components/defect-report";
99
import { Desc, DescList } from "@components/desc-list";
10+
import Missing from "@components/Missing.astro";
11+
import { Revision, RevisionBlock } from "@components/revision";
1012

1113
Specifies that an instance of the type can be default constructed.
1214

@@ -44,15 +46,15 @@ Non-object types (function types, reference types, and the (possibly cv-qualifie
4446
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
4547

4648
<DRList>
47-
<DR kind="lwg 724" id={1} std="C++98">
49+
<DR kind="lwg" id={724} std="C++98">
4850
<Fragment slot="behavior-published">
4951
the requirements of _DefaultConstructible_ were missing
5052
</Fragment>
5153
<Fragment slot="correct-behavior">
5254
added
5355
</Fragment>
5456
</DR>
55-
<DR kind="lwg 2170" id={1} std="C++98">
57+
<DR kind="lwg" id={2170} std="C++98">
5658
<Fragment slot="behavior-published">
5759
initialzing an object of a _DefaultConstructible_ type with an
5860
empty initializer could only result in value-initialization
@@ -67,21 +69,21 @@ empty initializer could only result in value-initialization
6769
<DescList>
6870
<Desc kind="class template">
6971
<Fragment slot="item">
70-
<RevisionBlock noborder since="C++11" vertical>
72+
<RevisionBlock noborder since="C++11">
7173
<Missing> `std::is_default_constructible` </Missing>
7274
</RevisionBlock>
73-
<RevisionBlock noborder since="C++11" vertical>
75+
<RevisionBlock noborder since="C++11">
7476
<Missing> `std::is_trivially_default_constructible` </Missing>
7577
</RevisionBlock>
76-
<RevisionBlock noborder since="C++11" vertical>
78+
<RevisionBlock noborder since="C++11">
7779
<Missing> `std::is_nothrow_default_constructible` </Missing>
7880
</RevisionBlock>
7981
</Fragment>
8082
checks if a type has a default constructor
8183
</Desc>
8284
<Desc kind="concept">
8385
<Fragment slot="item">
84-
<RevisionBlock noborder since="C++20" vertical>
86+
<RevisionBlock noborder since="C++20">
8587
<Missing> `default_initializable` </Missing>
8688
</RevisionBlock>
8789
</Fragment>

src/content/docs/cpp/language/named_req/Destructible.mdx renamed to src/content/docs/cpp/language/named_req/destructible.mdx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ cppdoc:
77

88
import { DR, DRList } from "@components/defect-report";
99
import { Desc, DescList } from "@components/desc-list";
10+
import Missing from "@components/Missing.astro";
11+
import { Revision, RevisionBlock } from "@components/revision";
1012

1113
Specifies that an instance of the type can be destructed.
1214

@@ -36,21 +38,21 @@ Thanks to pseudo destructor call, all scalar types meet the requirement of Destr
3638
<DescList>
3739
<Desc kind="class template">
3840
<Fragment slot="item">
39-
<RevisionBlock noborder since="C++11" vertical>
41+
<RevisionBlock noborder since="C++11">
4042
<Missing> `std::is_destructible` </Missing>
4143
</RevisionBlock>
42-
<RevisionBlock noborder since="C++11" vertical>
44+
<RevisionBlock noborder since="C++11">
4345
<Missing> `std::is_trivially_destructible` </Missing>
4446
</RevisionBlock>
45-
<RevisionBlock noborder since="C++11" vertical>
47+
<RevisionBlock noborder since="C++11">
4648
<Missing> `std::is_nothrow_destructible` </Missing>
4749
</RevisionBlock>
4850
</Fragment>
4951
checks if a type has a non-deleted destructor
5052
</Desc>
5153
<Desc kind="concept">
5254
<Fragment slot="item">
53-
<RevisionBlock noborder since="C++20" vertical>
55+
<RevisionBlock noborder since="C++20">
5456
<Missing> `destructible` </Missing>
5557
</RevisionBlock>
5658
</Fragment>

src/content/docs/cpp/language/named_req/Hash.mdx renamed to src/content/docs/cpp/language/named_req/hash.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ cppdoc:
77

88
import { DR, DRList } from "@components/defect-report";
99
import { Desc, DescList } from "@components/desc-list";
10+
import DocLink from "@components/DocLink.astro"
11+
import { Revision, RevisionBlock } from "@components/revision";
1012

1113
A ***Hash*** is a function object for which the output depends only on the input and has a very low probability of yielding the same output given different input values.
1214

@@ -46,7 +48,7 @@ The following expressions must be valid and have their specified effects.
4648
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
4749

4850
<DRList>
49-
<DR kind="lwg 2291" id={1} std="C++11">
51+
<DR kind="lwg" id={2291} std="C++11">
5052
<Fragment slot="behavior-published">
5153
same results for same arguments were required in all cases
5254
</Fragment>
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
---
2+
title: "C++ named requirements: Swappable"
3+
cppdoc:
4+
revision:
5+
since: C++11
6+
---
7+
8+
import { CppHeader } from "@components/header";
9+
import { DR, DRList } from "@components/defect-report";
10+
import { Desc, DescList } from "@components/desc-list";
11+
import Missing from "@components/Missing.astro";
12+
import { Revision, RevisionBlock } from "@components/revision";
13+
14+
Any lvalue or rvalue of this type can be swapped with any lvalue or rvalue of some other type, using unqualified function call <Missing> `swap()` </Missing> in the context where both `std::swap` and the user-defined `swap()`s are visible.
15+
16+
17+
## Requirements
18+
19+
Type U is swappable with type T if, for any object u of type U and any object t of type T,
20+
21+
Given
22+
23+
- `u`, an expression of type `T`.
24+
25+
- `u`, an lvalue expression of type `Key`.
26+
<table>
27+
<thead>
28+
<tr>
29+
<th> Expression </th>
30+
<th> Requirements </th>
31+
<th> Semantics </th>
32+
</tr>
33+
</thead>
34+
<tbody>
35+
<tr>
36+
<td>
37+
```c++
38+
#include <algorithm> // until C++11
39+
#include <utility> // since C++11
40+
using std::swap;
41+
swap(u, t);
42+
```
43+
</td>
44+
<td>
45+
After the call, the value of `t` is the value held by `u` before the call, and the value of `u` is the value held by `t` before the call.
46+
</td>
47+
<td>
48+
Calls the function named `swap()` found by overload resolution among all functions with that name that are found by argument-dependent lookup and the two `std::swap` templates defined in the header
49+
50+
<RevisionBlock until="C++11" noborder> <CppHeader name="algorithm" /> </RevisionBlock>
51+
<RevisionBlock since="C++11" noborder> <CppHeader name="utility" /> </RevisionBlock>
52+
</td>
53+
</tr>
54+
<tr>
55+
<td>
56+
```c++
57+
#include <algorithm> // until C++11
58+
#include <utility> // since C++11
59+
using std::swap;
60+
swap(u, t);
61+
```
62+
</td>
63+
<td>
64+
Same
65+
</td>
66+
<td>
67+
Same
68+
</td>
69+
</tr>
70+
</tbody>
71+
</table>
72+
73+
Many standard library functions (for example, many algorithms) expect their arguments to satisfy Swappable, which means that any time the standard library performs a swap, it uses the equivalent of using std::swap; swap(t, u);.
74+
75+
Typical implementations either
76+
77+
1. Define a non-member swap in the enclosing namespace, which may forward to a member swap if access to non-public data members is required.
78+
2. Define a friend function in-class (this approach hides the class-specific swap from name lookup other than ADL).
79+
80+
## Notes
81+
82+
Notes
83+
It is unspecified whether <RevisionBlock until="C++11" noborder> <CppHeader name="algorithm" /> </RevisionBlock>
84+
<RevisionBlock since="C++11" noborder> <CppHeader name="utility" /> </RevisionBlock> is actually included when the standard library functions perform the swap, so the user-provided swap() should not expect it to be included.
85+
86+
87+
## Example
88+
89+
```c++
90+
#include <iostream>
91+
#include <vector>
92+
93+
struct IntVector
94+
{
95+
std::vector<int> v;
96+
97+
IntVector& operator=(IntVector) = delete; // not assignable
98+
99+
void swap(IntVector& other)
100+
{
101+
v.swap(other.v);
102+
}
103+
104+
void operator()(auto rem, auto term = " ")
105+
{
106+
std::cout << rem << "{{";
107+
for (int n{}; int e : v)
108+
std::cout << (n++ ? ", " : "") << e;
109+
std::cout << "}}" << term;
110+
}
111+
};
112+
113+
void swap(IntVector& v1, IntVector& v2)
114+
{
115+
v1.swap(v2);
116+
}
117+
118+
int main()
119+
{
120+
IntVector v1{{1, 1, 1, 1}}, v2{{2222, 2222}};
121+
122+
auto prn = [&]{ v1("v1", ", "), v2("v2", ";\n"); };
123+
124+
// std::swap(v1, v2); // Compiler error! std::swap requires MoveAssignable
125+
prn();
126+
std::iter_swap(&v1, &v2); // OK: library calls unqualified swap()
127+
prn();
128+
std::ranges::swap(v1, v2); // OK: library calls unqualified swap()
129+
prn();
130+
}
131+
```
132+
133+
Output:
134+
135+
```
136+
v1{{1, 1, 1, 1}}, v2{{2222, 2222}};
137+
v1{{2222, 2222}}, v2{{1, 1, 1, 1}};
138+
v1{{1, 1, 1, 1}}, v2{{2222, 2222}};
139+
```
140+
141+
## Defect reports
142+
143+
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
144+
<DRList>
145+
<DR kind="lwg" id={226} std="C++98">
146+
<Fragment slot="behavior-published">
147+
it was unclear how the standard library uses swap
148+
</Fragment>
149+
<Fragment slot="correct-behavior">
150+
clarified to use both `std::` and ADL-found swap
151+
</Fragment>
152+
</DR>
153+
</DRList>
154+
## See also
155+
156+
<DescList>
157+
<Desc kind="class template">
158+
<Fragment slot="item">
159+
<RevisionBlock noborder since="C++17" >
160+
<Missing> `std::is_swappable_with` </Missing>
161+
</RevisionBlock>
162+
<RevisionBlock noborder since="C++17" >
163+
<Missing> `std::is_swappable` </Missing>
164+
</RevisionBlock>
165+
<RevisionBlock noborder since="C++17" >
166+
<Missing> `std::is_nothrow_swappable_with` </Missing>
167+
</RevisionBlock>
168+
<RevisionBlock noborder since="C++17" >
169+
<Missing> `std::is_nothrow_swappable` </Missing>
170+
</RevisionBlock>
171+
</Fragment>
172+
checks if objects of a type can be swapped with objects of same or different type
173+
</Desc>
174+
<Desc kind="concept">
175+
<Fragment slot="item">
176+
<RevisionBlock noborder since="C++20">
177+
<Missing> `swappable` </Missing> <br/>
178+
<Missing> `swappable_with` </Missing>
179+
</RevisionBlock>
180+
</Fragment>
181+
specifies that a type can be swapped or that two types can be swapped with each other
182+
</Desc>
183+
</DescList>
184+

0 commit comments

Comments
 (0)