|
12 | 12 |
|
13 | 13 | <discussion>
|
14 | 14 | <p>
|
15 |
| -<paper num="P0591R4"/> updated the definition of uses-allocator construction to specially handle `pair`. |
16 |
| -Per <sref ref="[tuple.cnstr]"/>/33, it seems that the `allocator_arg_t` constructors should also be |
17 |
| -updated to handle `pair`. However, such a change doesn't seem intended in <paper num="P0591R4"/>, |
18 |
| -and it would significantly complicate tuple. Currently, implementations consistently don't update |
19 |
| -these constructors in C++20. |
| 15 | +Before <paper num="P0591R4"/>, only `scoped_allocator_adaptor::construct` and |
| 16 | +`polymorphic_allocator::construct` specially handled `pair` for the purpose of uses-allocator |
| 17 | +construction. The primary definition of uses-allocator construction (in e.g., |
| 18 | +<paper num="N4659"/> [allocator.uses.construction]) did not specially handle `pair`. |
| 19 | +The `allocator_arg_t` constructors of `tuple`, which were specified to construct `tuple` |
| 20 | +elements with uses-allocator constructor (per e.g., <paper num="N4659"/> [tuple.cnstr] p26), |
| 21 | +did not specially handle `pair` either. |
20 | 22 | <p/>
|
21 |
| -Perhaps we should explicitly say that the `allocator_arg_t` constructors don't specially handle `pair`. |
| 23 | +<paper num="P0591R4"/> redefined uses-allocator construction in terms of `make_obj_using_allocator` |
| 24 | +in [allocator.uses.construction] p1 as: |
| 25 | +</p> |
| 26 | +<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;"> |
| 27 | +<p> |
| 28 | +When applied to the construction of an object of type `T`, it is equivalent to initializing it |
| 29 | +with the value of the expression <tt>make_obj_using_allocator<T>(alloc, args...)</tt>, described below. |
| 30 | +</p> |
| 31 | +</blockquote> |
| 32 | +<p> |
| 33 | +And the new definition does handle `pair`. As the specification of `allocator_arg_t` constructors of |
| 34 | +`tuple` (now in <sref ref="[tuple.cnstr]"/> p33) still refer to uses-allocator construction as-is, |
| 35 | +these constructors should construct a `pair` element in a way equivalent to `make_obj_using_allocator` now. |
| 36 | +<p/> |
| 37 | +The following example shows the behavioral difference. |
| 38 | +</p> |
| 39 | +<blockquote><pre> |
| 40 | +#include <cstddef> |
| 41 | +#include <utility> |
| 42 | +#include <tuple> |
| 43 | +#include <memory> |
| 44 | +#include <vector> |
| 45 | +#include <cassert> |
| 46 | + |
| 47 | +template<class T> |
| 48 | +class payload_ator { |
| 49 | + int payload{}; |
| 50 | + |
| 51 | +public: |
| 52 | + using value_type = T; |
| 53 | + |
| 54 | + payload_ator() = default; |
| 55 | + |
| 56 | + constexpr explicit payload_ator(int n) noexcept : payload{n} {} |
| 57 | + |
| 58 | + template<class U> |
| 59 | + constexpr explicit payload_ator(payload_ator<U> a) noexcept : payload{a.payload} {} |
| 60 | + |
| 61 | + friend bool operator==(payload_ator, payload_ator) = default; |
| 62 | + |
| 63 | + template<class U> |
| 64 | + friend constexpr bool operator==(payload_ator x, payload_ator<U> y) noexcept { |
| 65 | + return x.payload == y.payload; |
| 66 | + } |
| 67 | + |
| 68 | + constexpr T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); } |
| 69 | + |
| 70 | + constexpr void deallocate(T* p, std::size_t n) { return std::allocator<T>{}.deallocate(p, n); } |
| 71 | + |
| 72 | + constexpr int get_payload() const noexcept { return payload; } |
| 73 | +}; |
| 74 | + |
| 75 | +bool test() { |
| 76 | + constexpr int in_v = 42; |
| 77 | + using my_pair_t = std::pair<int, std::vector<int, payload_ator<int>>>; |
| 78 | + std::tuple<my_pair_t> t(std::allocator_arg, payload_ator<int>{in_v}); |
| 79 | + auto out_v = std::get<0>(t).second.get_allocator().get_payload(); |
| 80 | + return in_v == out_v; |
| 81 | +} |
| 82 | + |
| 83 | +int main() { |
| 84 | + assert(test()); // <span style="color:#C80000;font-weight:bold">passes only if allocator_arg_t constructors of tuple specially handle pair</span> |
| 85 | +} |
| 86 | +</pre></blockquote> |
| 87 | +<p> |
| 88 | +However, the behavioral changes of these constructors were not discussed in <paper num="P0591R4"/>, |
| 89 | +and existing implementations that claim full implementation of <paper num="P0591R4"/> (MSVC STL and libstdc++) |
| 90 | +did not change these constructors (<a href="https://godbolt.org/z/6vnP78nqW">demo</a>). |
| 91 | +<p/> |
| 92 | +Given that implementations did not recognize changes of `allocator_arg_t` constructors as part of the paper, |
| 93 | +and special handling of `pair` would significantly complicate these constructors, perhaps we should |
| 94 | +explicitly specify that these constructors behave as if special handling for `pair` were missing. |
22 | 95 | </p>
|
23 | 96 | </discussion>
|
24 | 97 |
|
|
0 commit comments