From Jason Turner

[map]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpyx2nx31v/{from.md → to.md} +71 -76
tmp/tmpyx2nx31v/{from.md → to.md} RENAMED
@@ -1,33 +1,32 @@
1
  ### Class template `map` <a id="map">[[map]]</a>
2
 
3
- #### Class template `map` overview <a id="map.overview">[[map.overview]]</a>
4
 
5
  A `map` is an associative container that supports unique keys (contains
6
  at most one of each key value) and provides for fast retrieval of values
7
  of another type `T` based on the keys. The `map` class supports
8
  bidirectional iterators.
9
 
10
- A `map` satisfies all of the requirements of a container, of a
11
- reversible container ([[container.requirements]]), of an associative
12
- container ([[associative.reqmts]]), and of an allocator-aware container
13
- (Table  [[tab:containers.allocatoraware]]). A `map` also provides most
14
- operations described in  [[associative.reqmts]] for unique keys. This
15
- means that a `map` supports the `a_uniq` operations in 
16
- [[associative.reqmts]] but not the `a_eq` operations. For a `map<Key,T>`
17
- the `key_type` is `Key` and the `value_type` is `pair<const Key,T>`.
18
- Descriptions are provided here only for operations on `map` that are not
19
- described in one of those tables or for operations where there is
20
- additional semantic information.
21
 
22
  ``` cpp
23
  namespace std {
24
  template<class Key, class T, class Compare = less<Key>,
25
  class Allocator = allocator<pair<const Key, T>>>
26
  class map {
27
  public:
28
- // types:
29
  using key_type = Key;
30
  using mapped_type = T;
31
  using value_type = pair<const Key, T>;
32
  using key_compare = Compare;
33
  using allocator_type = Allocator;
@@ -40,11 +39,11 @@ namespace std {
40
  using iterator = implementation-defined // type of map::iterator; // see [container.requirements]
41
  using const_iterator = implementation-defined // type of map::const_iterator; // see [container.requirements]
42
  using reverse_iterator = std::reverse_iterator<iterator>;
43
  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
44
  using node_type = unspecified;
45
- using insert_return_type = INSERT_RETURN_TYPE<iterator, node_type>;
46
 
47
  class value_compare {
48
  friend class map;
49
  protected:
50
  Compare comp;
@@ -80,11 +79,11 @@ namespace std {
80
  noexcept(allocator_traits<Allocator>::is_always_equal::value &&
81
  is_nothrow_move_assignable_v<Compare>);
82
  map& operator=(initializer_list<value_type>);
83
  allocator_type get_allocator() const noexcept;
84
 
85
- // iterators:
86
  iterator begin() noexcept;
87
  const_iterator begin() const noexcept;
88
  iterator end() noexcept;
89
  const_iterator end() const noexcept;
90
 
@@ -96,20 +95,20 @@ namespace std {
96
  const_iterator cbegin() const noexcept;
97
  const_iterator cend() const noexcept;
98
  const_reverse_iterator crbegin() const noexcept;
99
  const_reverse_iterator crend() const noexcept;
100
 
101
- // capacity:
102
- bool empty() const noexcept;
103
  size_type size() const noexcept;
104
  size_type max_size() const noexcept;
105
 
106
  // [map.access], element access
107
- T& operator[](const key_type& x);
108
- T& operator[](key_type&& x);
109
- T& at(const key_type& x);
110
- const T& at(const key_type& x) const;
111
 
112
  // [map.modifiers], modifiers
113
  template<class... Args> pair<iterator, bool> emplace(Args&&... args);
114
  template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
115
  pair<iterator, bool> insert(const value_type& x);
@@ -161,23 +160,26 @@ namespace std {
161
  template<class C2>
162
  void merge(multimap<Key, T, C2, Allocator>& source);
163
  template<class C2>
164
  void merge(multimap<Key, T, C2, Allocator>&& source);
165
 
166
- // observers:
167
  key_compare key_comp() const;
168
  value_compare value_comp() const;
169
 
170
- // map operations:
171
  iterator find(const key_type& x);
172
  const_iterator find(const key_type& x) const;
173
  template<class K> iterator find(const K& x);
174
  template<class K> const_iterator find(const K& x) const;
175
 
176
  size_type count(const key_type& x) const;
177
  template<class K> size_type count(const K& x) const;
178
 
 
 
 
179
  iterator lower_bound(const key_type& x);
180
  const_iterator lower_bound(const key_type& x) const;
181
  template<class K> iterator lower_bound(const K& x);
182
  template<class K> const_iterator lower_bound(const K& x) const;
183
 
@@ -192,56 +194,37 @@ namespace std {
192
  pair<iterator, iterator> equal_range(const K& x);
193
  template<class K>
194
  pair<const_iterator, const_iterator> equal_range(const K& x) const;
195
  };
196
 
197
- template<class InputIterator, class Compare = less<iter_key_t<InputIterator>>,
198
- class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
199
  map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
200
- -> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Compare, Allocator>;
201
 
202
  template<class Key, class T, class Compare = less<Key>,
203
  class Allocator = allocator<pair<const Key, T>>>
204
- map(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator())
205
  -> map<Key, T, Compare, Allocator>;
206
 
207
  template<class InputIterator, class Allocator>
208
  map(InputIterator, InputIterator, Allocator)
209
- -> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
210
- less<iter_key_t<InputIterator>>, Allocator>;
211
 
212
  template<class Key, class T, class Allocator>
213
- map(initializer_list<pair<const Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>;
214
 
215
- template <class Key, class T, class Compare, class Allocator>
216
- bool operator==(const map<Key, T, Compare, Allocator>& x,
217
- const map<Key, T, Compare, Allocator>& y);
218
- template <class Key, class T, class Compare, class Allocator>
219
- bool operator< (const map<Key, T, Compare, Allocator>& x,
220
- const map<Key, T, Compare, Allocator>& y);
221
- template <class Key, class T, class Compare, class Allocator>
222
- bool operator!=(const map<Key, T, Compare, Allocator>& x,
223
- const map<Key, T, Compare, Allocator>& y);
224
- template <class Key, class T, class Compare, class Allocator>
225
- bool operator> (const map<Key, T, Compare, Allocator>& x,
226
- const map<Key, T, Compare, Allocator>& y);
227
- template <class Key, class T, class Compare, class Allocator>
228
- bool operator>=(const map<Key, T, Compare, Allocator>& x,
229
- const map<Key, T, Compare, Allocator>& y);
230
- template <class Key, class T, class Compare, class Allocator>
231
- bool operator<=(const map<Key, T, Compare, Allocator>& x,
232
- const map<Key, T, Compare, Allocator>& y);
233
-
234
- // [map.special], specialized algorithms
235
  template<class Key, class T, class Compare, class Allocator>
236
  void swap(map<Key, T, Compare, Allocator>& x,
237
  map<Key, T, Compare, Allocator>& y)
238
  noexcept(noexcept(x.swap(y)));
239
  }
240
  ```
241
 
242
- #### `map` constructors, copy, and assignment <a id="map.cons">[[map.cons]]</a>
243
 
244
  ``` cpp
245
  explicit map(const Compare& comp, const Allocator& = Allocator());
246
  ```
247
 
@@ -261,62 +244,61 @@ object and allocator, and inserts elements from the range \[`first`,
261
  `last`).
262
 
263
  *Complexity:* Linear in N if the range \[`first`, `last`) is already
264
  sorted using `comp` and otherwise N log N, where N is `last - first`.
265
 
266
- #### `map` element access <a id="map.access">[[map.access]]</a>
267
 
268
  ``` cpp
269
- T& operator[](const key_type& x);
270
  ```
271
 
272
  *Effects:* Equivalent to: `return try_emplace(x).first->second;`
273
 
274
  ``` cpp
275
- T& operator[](key_type&& x);
276
  ```
277
 
278
  *Effects:* Equivalent to: `return try_emplace(move(x)).first->second;`
279
 
280
  ``` cpp
281
- T& at(const key_type& x);
282
- const T& at(const key_type& x) const;
283
  ```
284
 
285
  *Returns:* A reference to the `mapped_type` corresponding to `x` in
286
  `*this`.
287
 
288
  *Throws:* An exception object of type `out_of_range` if no such element
289
  is present.
290
 
291
  *Complexity:* Logarithmic.
292
 
293
- #### `map` modifiers <a id="map.modifiers">[[map.modifiers]]</a>
294
 
295
  ``` cpp
296
  template<class P>
297
  pair<iterator, bool> insert(P&& x);
298
  template<class P>
299
  iterator insert(const_iterator position, P&& x);
300
  ```
301
 
 
 
302
  *Effects:* The first form is equivalent to
303
  `return emplace(std::forward<P>(x))`. The second form is equivalent to
304
  `return emplace_hint(position, std::forward<P>(x))`.
305
 
306
- *Remarks:* These signatures shall not participate in overload resolution
307
- unless `is_constructible_v<value_type, P&&>` is `true`.
308
-
309
  ``` cpp
310
  template<class... Args>
311
  pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
312
  template<class... Args>
313
  iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
314
  ```
315
 
316
- *Requires:* `value_type` shall be `EmplaceConstructible` into `map` from
317
- `piecewise_construct`, `forward_as_tuple(k)`,
318
  `forward_as_tuple(std::forward<Args>(args)...)`.
319
 
320
  *Effects:* If the map already contains an element whose key is
321
  equivalent to `k`, there is no effect. Otherwise inserts an object of
322
  type `value_type` constructed with `piecewise_construct`,
@@ -333,12 +315,12 @@ template <class... Args>
333
  pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
334
  template<class... Args>
335
  iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
336
  ```
337
 
338
- *Requires:* `value_type` shall be `EmplaceConstructible` into `map` from
339
- `piecewise_construct`, `forward_as_tuple(std::move(k))`,
340
  `forward_as_tuple(std::forward<Args>(args)...)`.
341
 
342
  *Effects:* If the map already contains an element whose key is
343
  equivalent to `k`, there is no effect. Otherwise inserts an object of
344
  type `value_type` constructed with `piecewise_construct`,
@@ -356,13 +338,14 @@ template <class M>
356
  pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
357
  template<class M>
358
  iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
359
  ```
360
 
361
- *Requires:* `is_assignable_v<mapped_type&, M&&>` shall be `true`.
362
- `value_type` shall be `EmplaceConstructible` into `map` from `k`,
363
- `forward<M>(obj)`.
 
364
 
365
  *Effects:* If the map already contains an element `e` whose key is
366
  equivalent to `k`, assigns `std::forward<M>(obj)` to `e.second`.
367
  Otherwise inserts an object of type `value_type` constructed with `k`,
368
  `std::forward<M>(obj)`.
@@ -378,13 +361,14 @@ template <class M>
378
  pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
379
  template<class M>
380
  iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
381
  ```
382
 
383
- *Requires:* `is_assignable_v<mapped_type&, M&&>` shall be `true`.
384
- `value_type` shall be `EmplaceConstructible` into `map` from `move(k)`,
385
- `forward<M>(obj)`.
 
386
 
387
  *Effects:* If the map already contains an element `e` whose key is
388
  equivalent to `k`, assigns `std::forward<M>(obj)` to `e.second`.
389
  Otherwise inserts an object of type `value_type` constructed with
390
  `std::move(k)`, `std::forward<M>(obj)`.
@@ -393,16 +377,27 @@ Otherwise inserts an object of type `value_type` constructed with
393
  pair is `true` if and only if the insertion took place. The returned
394
  iterator points to the map element whose key is equivalent to `k`.
395
 
396
  *Complexity:* The same as `emplace` and `emplace_hint`, respectively.
397
 
398
- #### `map` specialized algorithms <a id="map.special">[[map.special]]</a>
399
 
400
  ``` cpp
401
- template <class Key, class T, class Compare, class Allocator>
402
- void swap(map<Key, T, Compare, Allocator>& x,
403
- map<Key, T, Compare, Allocator>& y)
404
- noexcept(noexcept(x.swap(y)));
405
  ```
406
 
407
- *Effects:* As if by `x.swap(y)`.
 
 
 
 
 
 
 
 
 
 
 
 
408
 
 
1
  ### Class template `map` <a id="map">[[map]]</a>
2
 
3
+ #### Overview <a id="map.overview">[[map.overview]]</a>
4
 
5
  A `map` is an associative container that supports unique keys (contains
6
  at most one of each key value) and provides for fast retrieval of values
7
  of another type `T` based on the keys. The `map` class supports
8
  bidirectional iterators.
9
 
10
+ A `map` meets all of the requirements of a container, of a reversible
11
+ container [[container.requirements]], of an associative container
12
+ [[associative.reqmts]], and of an allocator-aware container (
13
+ [[container.alloc.req]]). A `map` also provides most operations
14
+ described in  [[associative.reqmts]] for unique keys. This means that a
15
+ `map` supports the `a_uniq` operations in  [[associative.reqmts]] but
16
+ not the `a_eq` operations. For a `map<Key,T>` the `key_type` is `Key`
17
+ and the `value_type` is `pair<const Key,T>`. Descriptions are provided
18
+ here only for operations on `map` that are not described in one of those
19
+ tables or for operations where there is additional semantic information.
 
20
 
21
  ``` cpp
22
  namespace std {
23
  template<class Key, class T, class Compare = less<Key>,
24
  class Allocator = allocator<pair<const Key, T>>>
25
  class map {
26
  public:
27
+ // types
28
  using key_type = Key;
29
  using mapped_type = T;
30
  using value_type = pair<const Key, T>;
31
  using key_compare = Compare;
32
  using allocator_type = Allocator;
 
39
  using iterator = implementation-defined // type of map::iterator; // see [container.requirements]
40
  using const_iterator = implementation-defined // type of map::const_iterator; // see [container.requirements]
41
  using reverse_iterator = std::reverse_iterator<iterator>;
42
  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
43
  using node_type = unspecified;
44
+ using insert_return_type = insert-return-type<iterator, node_type>;
45
 
46
  class value_compare {
47
  friend class map;
48
  protected:
49
  Compare comp;
 
79
  noexcept(allocator_traits<Allocator>::is_always_equal::value &&
80
  is_nothrow_move_assignable_v<Compare>);
81
  map& operator=(initializer_list<value_type>);
82
  allocator_type get_allocator() const noexcept;
83
 
84
+ // iterators
85
  iterator begin() noexcept;
86
  const_iterator begin() const noexcept;
87
  iterator end() noexcept;
88
  const_iterator end() const noexcept;
89
 
 
95
  const_iterator cbegin() const noexcept;
96
  const_iterator cend() const noexcept;
97
  const_reverse_iterator crbegin() const noexcept;
98
  const_reverse_iterator crend() const noexcept;
99
 
100
+ // capacity
101
+ [[nodiscard]] bool empty() const noexcept;
102
  size_type size() const noexcept;
103
  size_type max_size() const noexcept;
104
 
105
  // [map.access], element access
106
+ mapped_type& operator[](const key_type& x);
107
+ mapped_type& operator[](key_type&& x);
108
+ mapped_type& at(const key_type& x);
109
+ const mapped_type& at(const key_type& x) const;
110
 
111
  // [map.modifiers], modifiers
112
  template<class... Args> pair<iterator, bool> emplace(Args&&... args);
113
  template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
114
  pair<iterator, bool> insert(const value_type& x);
 
160
  template<class C2>
161
  void merge(multimap<Key, T, C2, Allocator>& source);
162
  template<class C2>
163
  void merge(multimap<Key, T, C2, Allocator>&& source);
164
 
165
+ // observers
166
  key_compare key_comp() const;
167
  value_compare value_comp() const;
168
 
169
+ // map operations
170
  iterator find(const key_type& x);
171
  const_iterator find(const key_type& x) const;
172
  template<class K> iterator find(const K& x);
173
  template<class K> const_iterator find(const K& x) const;
174
 
175
  size_type count(const key_type& x) const;
176
  template<class K> size_type count(const K& x) const;
177
 
178
+ bool contains(const key_type& x) const;
179
+ template<class K> bool contains(const K& x) const;
180
+
181
  iterator lower_bound(const key_type& x);
182
  const_iterator lower_bound(const key_type& x) const;
183
  template<class K> iterator lower_bound(const K& x);
184
  template<class K> const_iterator lower_bound(const K& x) const;
185
 
 
194
  pair<iterator, iterator> equal_range(const K& x);
195
  template<class K>
196
  pair<const_iterator, const_iterator> equal_range(const K& x) const;
197
  };
198
 
199
+ template<class InputIterator, class Compare = less<iter-key-type<InputIterator>>,
200
+ class Allocator = allocator<iter-to-alloc-type<InputIterator>>>
201
  map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
202
+ -> map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Compare, Allocator>;
203
 
204
  template<class Key, class T, class Compare = less<Key>,
205
  class Allocator = allocator<pair<const Key, T>>>
206
+ map(initializer_list<pair<Key, T>>, Compare = Compare(), Allocator = Allocator())
207
  -> map<Key, T, Compare, Allocator>;
208
 
209
  template<class InputIterator, class Allocator>
210
  map(InputIterator, InputIterator, Allocator)
211
+ -> map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>,
212
+ less<iter-key-type<InputIterator>>, Allocator>;
213
 
214
  template<class Key, class T, class Allocator>
215
+ map(initializer_list<pair<Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>;
216
 
217
+ // swap
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  template<class Key, class T, class Compare, class Allocator>
219
  void swap(map<Key, T, Compare, Allocator>& x,
220
  map<Key, T, Compare, Allocator>& y)
221
  noexcept(noexcept(x.swap(y)));
222
  }
223
  ```
224
 
225
+ #### Constructors, copy, and assignment <a id="map.cons">[[map.cons]]</a>
226
 
227
  ``` cpp
228
  explicit map(const Compare& comp, const Allocator& = Allocator());
229
  ```
230
 
 
244
  `last`).
245
 
246
  *Complexity:* Linear in N if the range \[`first`, `last`) is already
247
  sorted using `comp` and otherwise N log N, where N is `last - first`.
248
 
249
+ #### Element access <a id="map.access">[[map.access]]</a>
250
 
251
  ``` cpp
252
+ mapped_type& operator[](const key_type& x);
253
  ```
254
 
255
  *Effects:* Equivalent to: `return try_emplace(x).first->second;`
256
 
257
  ``` cpp
258
+ mapped_type& operator[](key_type&& x);
259
  ```
260
 
261
  *Effects:* Equivalent to: `return try_emplace(move(x)).first->second;`
262
 
263
  ``` cpp
264
+ mapped_type& at(const key_type& x);
265
+ const mapped_type& at(const key_type& x) const;
266
  ```
267
 
268
  *Returns:* A reference to the `mapped_type` corresponding to `x` in
269
  `*this`.
270
 
271
  *Throws:* An exception object of type `out_of_range` if no such element
272
  is present.
273
 
274
  *Complexity:* Logarithmic.
275
 
276
+ #### Modifiers <a id="map.modifiers">[[map.modifiers]]</a>
277
 
278
  ``` cpp
279
  template<class P>
280
  pair<iterator, bool> insert(P&& x);
281
  template<class P>
282
  iterator insert(const_iterator position, P&& x);
283
  ```
284
 
285
+ *Constraints:* `is_constructible_v<value_type, P&&>` is `true`.
286
+
287
  *Effects:* The first form is equivalent to
288
  `return emplace(std::forward<P>(x))`. The second form is equivalent to
289
  `return emplace_hint(position, std::forward<P>(x))`.
290
 
 
 
 
291
  ``` cpp
292
  template<class... Args>
293
  pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
294
  template<class... Args>
295
  iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
296
  ```
297
 
298
+ *Preconditions:* `value_type` is *Cpp17EmplaceConstructible* into `map`
299
+ from `piecewise_construct`, `forward_as_tuple(k)`,
300
  `forward_as_tuple(std::forward<Args>(args)...)`.
301
 
302
  *Effects:* If the map already contains an element whose key is
303
  equivalent to `k`, there is no effect. Otherwise inserts an object of
304
  type `value_type` constructed with `piecewise_construct`,
 
315
  pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
316
  template<class... Args>
317
  iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
318
  ```
319
 
320
+ *Preconditions:* `value_type` is *Cpp17EmplaceConstructible* into `map`
321
+ from `piecewise_construct`, `forward_as_tuple(std::move(k))`,
322
  `forward_as_tuple(std::forward<Args>(args)...)`.
323
 
324
  *Effects:* If the map already contains an element whose key is
325
  equivalent to `k`, there is no effect. Otherwise inserts an object of
326
  type `value_type` constructed with `piecewise_construct`,
 
338
  pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
339
  template<class M>
340
  iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
341
  ```
342
 
343
+ *Mandates:* `is_assignable_v<mapped_type&, M&&>` is `true`.
344
+
345
+ *Preconditions:* `value_type` is *Cpp17EmplaceConstructible* into `map`
346
+ from `k`, `forward<M>(obj)`.
347
 
348
  *Effects:* If the map already contains an element `e` whose key is
349
  equivalent to `k`, assigns `std::forward<M>(obj)` to `e.second`.
350
  Otherwise inserts an object of type `value_type` constructed with `k`,
351
  `std::forward<M>(obj)`.
 
361
  pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
362
  template<class M>
363
  iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
364
  ```
365
 
366
+ *Mandates:* `is_assignable_v<mapped_type&, M&&>` is `true`.
367
+
368
+ *Preconditions:* `value_type` is *Cpp17EmplaceConstructible* into `map`
369
+ from `move(k)`, `forward<M>(obj)`.
370
 
371
  *Effects:* If the map already contains an element `e` whose key is
372
  equivalent to `k`, assigns `std::forward<M>(obj)` to `e.second`.
373
  Otherwise inserts an object of type `value_type` constructed with
374
  `std::move(k)`, `std::forward<M>(obj)`.
 
377
  pair is `true` if and only if the insertion took place. The returned
378
  iterator points to the map element whose key is equivalent to `k`.
379
 
380
  *Complexity:* The same as `emplace` and `emplace_hint`, respectively.
381
 
382
+ #### Erasure <a id="map.erasure">[[map.erasure]]</a>
383
 
384
  ``` cpp
385
+ template<class Key, class T, class Compare, class Allocator, class Predicate>
386
+ typename map<Key, T, Compare, Allocator>::size_type
387
+ erase_if(map<Key, T, Compare, Allocator>& c, Predicate pred);
 
388
  ```
389
 
390
+ *Effects:* Equivalent to:
391
+
392
+ ``` cpp
393
+ auto original_size = c.size();
394
+ for (auto i = c.begin(), last = c.end(); i != last; ) {
395
+ if (pred(*i)) {
396
+ i = c.erase(i);
397
+ } else {
398
+ ++i;
399
+ }
400
+ }
401
+ return original_size - c.size();
402
+ ```
403