|
| 1 | +<?xml version='1.0' encoding='utf-8' standalone='no'?> |
| 2 | +<!DOCTYPE issue SYSTEM "lwg-issue.dtd"> |
| 3 | + |
| 4 | +<issue num="4503" status="New"> |
| 5 | +<title>Use of `std::common_reference_with` in `std::assignable_from` seems incorrect</title> |
| 6 | +<section><sref ref="[concept.assignable]"/></section> |
| 7 | +<submitter>Jiang An</submitter> |
| 8 | +<date>24 Dec 2025</date> |
| 9 | +<priority>99</priority> |
| 10 | + |
| 11 | +<discussion> |
| 12 | +<p> |
| 13 | +Currently, <tt>std::assignable_from<std::unique_ptr<int>&, std::nullptr_t></tt> is `false`, |
| 14 | +because the common reference type of <tt>unique_ptr<int>&</tt> and `nullptr_t` is |
| 15 | +<tt>unique_ptr<int></tt>, and a const <tt>unique_ptr<int></tt> lvalue can't be converted to the |
| 16 | +common reference type. |
| 17 | +<p/> |
| 18 | +Such design seems counter-intuitive and valueless. When `common_reference_with` is modeled, |
| 19 | +one can use the common reference type in some non-generic, homogeneous interfaces. However, |
| 20 | +it should be clear enough that the type isn't expected to be used in assignment. |
| 21 | +<p/> |
| 22 | +The earliest form of the design can be found in |
| 23 | +<a href="https://github.com/ericniebler/stl2/pull/150">ericniebler/stl2#150</a>, where cases |
| 24 | +involving move-only types didn't seem analyzed. In any case, if we want `ranges::advance` to perform |
| 25 | +assignment only when `I` and `S` are common enough, we should just limit the `common_reference_with` |
| 26 | +requirements to `ranges::advance`. |
| 27 | +</p> |
| 28 | +</discussion> |
| 29 | + |
| 30 | +<resolution> |
| 31 | +<p> |
| 32 | +This wording is relative to <paper num="N5032"/>. |
| 33 | +</p> |
| 34 | + |
| 35 | +<ol> |
| 36 | +<li><p>Modify <sref ref="[concept.assignable]"/> as indicated:</p> |
| 37 | + |
| 38 | +<blockquote> |
| 39 | +<pre> |
| 40 | +template<class LHS, class RHS> |
| 41 | + concept assignable_from = |
| 42 | + is_lvalue_reference_v<LHS> && |
| 43 | + <del>common_reference_with<const remove_reference_t<LHS>&, const remove_reference_t<RHS>&> &&</del> |
| 44 | + requires(LHS lhs, RHS&& rhs) { |
| 45 | + { lhs = std::forward<RHS>(rhs) } -> same_as<LHS>; |
| 46 | + }; |
| 47 | +</pre> |
| 48 | +</blockquote> |
| 49 | +</li> |
| 50 | + |
| 51 | +</ol> |
| 52 | +</resolution> |
| 53 | + |
| 54 | +</issue> |
0 commit comments