220 41298 <2ff776bd-453f-4af1-af45-a16816008a29@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Mingxin Wang <wmx16835vv@163.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Thoughts about std::forward
Date: Tue, 25 Dec 2018 19:38:05 -0800 (PST)
Lines: 214
Approved: news@gmane.org
Message-ID: <2ff776bd-453f-4af1-af45-a16816008a29@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_1437_1567527052.1545795485356"
X-Trace: blaine.gmane.org 1545795362 16640 195.159.176.226 (26 Dec 2018 03:36:02 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Wed, 26 Dec 2018 03:36:02 +0000 (UTC)
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBDNMBNHJWIGBBHXPRPQQKGQELOK5G7Q@isocpp.org Wed Dec 26 04:35:58 2018
Return-path: <std-proposals+bncBDNMBNHJWIGBBHXPRPQQKGQELOK5G7Q@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-yb1-f200.google.com ([209.85.219.200])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBDNMBNHJWIGBBHXPRPQQKGQELOK5G7Q@isocpp.org>)
	id 1gbzzB-0004C8-Gf
	for gclcip-std-proposals@m.gmane.org; Wed, 26 Dec 2018 04:35:57 +0100
Original-Received: by mail-yb1-f200.google.com with SMTP id 196sf5851094ybf.8
        for <gclcip-std-proposals@m.gmane.org>; Tue, 25 Dec 2018 19:38:08 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:message-id:subject:mime-version:x-original-sender
         :reply-to:precedence:mailing-list:list-id:list-post:list-help
         :list-archive:list-subscribe:list-unsubscribe;
        bh=KdoyR4AQQ5I3Bpuoa92o/GkaqmA2uwe1BUXKKCpGunQ=;
        b=1btj7+3B23f6bmuO8+QqtsKWtMGEK9Nec/hjY/Y8SYEjEWaZA78D2xoqPaIDTJDNLf
         2XMxd4p+hxRkmV14GG6viuVjKFeDFf34N1ws/ztIgzHWxO8mzfCwiJlfxuazq0wVzZWx
         +K++UWh2IfDY01n0HIIp2kGXntvoXq44MySHs7tOyhcS0A/pIAUclV4rIezLDYw51/zL
         7vcQXIhnLQmZgy1QJ/EMfj5g9N1lfrf0hOGeDll0CmZMm+sA6VhdcKzksDj2Ai7Efq0w
         2q870+pYYxSzHPz+P/ojo6gPD6vutc9jI6GQtBiMevhs4EN5UBLiKjRunloz/yrz4z5L
         /PSg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:date:from:to:message-id:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=KdoyR4AQQ5I3Bpuoa92o/GkaqmA2uwe1BUXKKCpGunQ=;
        b=tt3NVOxISNwzmP9+ElcY/9GK5Dbo5vvfRMY2sczkGktI2cfsWQHnGsSelsc7hMMibS
         HolgI3VDacpoY/+LEFPB3LZzCg4H0ukwNb+V3swfFZ0EImUnWlbLdzWpGidFoWmk5xga
         OX8VsD3IR7TBc8H4dQh2g9zb8i6HJf1+WGwZmKTnnHvvKvukTtgSs1qU9QMGqKt51xnC
         Yb8/eUyRDQZIXW/AQj21vPTg8UVrRi/M2wruz7cxdu+zfZRFc1P7BIJHbfhhToCmlxP4
         GqPnesdIxv3RZjHIOteoyHj0Gf0EtVHuuwnANJY5donbWvLo4YlTOopEhLZurycFi7AT
         nZNQ==
X-Gm-Message-State: AA+aEWYCn5SZCUGWIjA6G8S1eJUmnBeedWHpGoC2RtFyYDPDEUw/jrwr
	t4HWIhj0PLpHjenrtGwZ9CJVtg==
X-Google-Smtp-Source: AFSGD/VIs0Kg4TCok9YB669sYZ2wA4lTuAGKPzDupk0Vp+3k1aZXhAD1juIqTz8JnrlWtyryo6xSFw==
X-Received: by 2002:a81:52c7:: with SMTP id g190mr10738862ywb.4.1545795487651;
        Tue, 25 Dec 2018 19:38:07 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 2002:a81:7d87:: with SMTP id y129ls7030356ywc.2.gmail; Tue, 25
 Dec 2018 19:38:06 -0800 (PST)
X-Received: by 2002:a81:9841:: with SMTP id p62mr197468ywg.0.1545795486159;
        Tue, 25 Dec 2018 19:38:06 -0800 (PST)
X-Original-Sender: wmx16835vv@163.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Spam-Checked-In-Group: std-proposals@isocpp.org
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:41298
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/41298>

------=_Part_1437_1567527052.1545795485356
Content-Type: multipart/alternative; 
	boundary="----=_Part_1438_47687471.1545795485356"

------=_Part_1438_47687471.1545795485356
Content-Type: text/plain; charset="UTF-8"

*The first idea:*

`std::forward` and `std::move` are commonly used in library design, 
especially in template metaprogramming libraries. Both of the two functions 
support rvalue references as input. However, I could not think of a 
meaningful use case that requires passing rvalue references to these 
functions. *Is there a concrete reason that `std::forward` and 
`std::move` should accept rvalue references?*

*The second idea:*

When designing template metaprogramming libraries, I found 
`std::reference_wrapper` useful when IMPLICITLY indicating a type with a 
value (maybe with qualifiers), and there are various function templates in 
the standard library that use this pattern. For example, `std::make_pair`, 
`std::make_typle`, `std::bind`, `std::invoke`, etc. *I think it could be a 
good idea to add handy utilities for implicit type deduction*, not only for 
3rd party libary vendor's convenience, but also to improve the wording of 
these function templates with similar semantics in the standard.

For instance, there should be a type template alias (corresponding to 
`std::decay`, let's may as well call it `extended_decay`) and a function 
template to forward the parameters (corresponding to `std::forward`, let's 
may as well call it `extended_forward`; rvale references are not supported 
for now). The following code is an implementation for the utilities that is 
currentely used in my libraries:

namespace detail {

template <class T>
struct reference_wrapper_traits {
  static inline constexpr bool is_reference_wrapper = false;
  using dereferenced_type = T;
};

template <class T>
struct reference_wrapper_traits<std::reference_wrapper<T>> {
  static inline constexpr bool is_reference_wrapper = true;
  using dereferenced_type = T&;
};

template <class T, bool W>
struct extended_forward_helper;

template <class T>
struct extended_forward_helper<T, false> {
  static inline T&& apply(T& t) { return static_cast<T&&>(t); }
};

template <class T>
struct extended_forward_helper<T, true> {
  static inline auto apply(T& t)
      -> typename 
reference_wrapper_traits<std::decay_t<T>>::dereferenced_type
      { return t.get(); }
};

}  // namespace detail

// This type refers to `std::decay_t<T>`, unless application of `std::decay`
// results in `std::reference_wrapper<X>` for some type `X`, in which case 
the
// deduced type is `X&`.
template <class T>
using extended_decay_t = typename detail::reference_wrapper_traits<
    std::decay_t<T>>::dereferenced_type;

// This function forwards an lvalue reference to its original reference 
type,
// unless `std::decay_t<T>` results in `std::reference_wrapper<X>` for some 
type
// `X`, in which case it returns the result of `value.get()`.
//
// Note: In case an lvalue reference may be returned, it is necessary to
// explicitly announce the return type. Otherwise, there could be an 
improper
// copy construction.
template <class T>
auto extended_forward(std::remove_reference_t<T>& value)
    -> std::conditional_t<
        
detail::reference_wrapper_traits<std::decay_t<T>>::is_reference_wrapper,
        typename detail::reference_wrapper_traits<std::decay_t<T>>
        ::dereferenced_type, T&&> {
  return detail::extended_forward_helper<T, 
detail::reference_wrapper_traits<
      std::decay_t<T>>::is_reference_wrapper>::apply(value);
}

What do you think of the ideas?

Mingxin Wang

-- 
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2ff776bd-453f-4af1-af45-a16816008a29%40isocpp.org.

------=_Part_1438_47687471.1545795485356
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div><i>The first idea:</i></div><div><br></div>`std::forw=
ard` and `std::move` are commonly used in library design, especially in tem=
plate metaprogramming libraries. Both of the two functions support rvalue r=
eferences as input. However, I could not think of a meaningful use case tha=
t requires passing rvalue references to these functions. <b>Is there a conc=
rete reason that `std::forward` and `std::move`=C2=A0should accept rvalue r=
eferences?</b><br><div><br></div><div><i>The second idea:</i></div><div><br=
></div><div>When designing template metaprogramming libraries, I found `std=
::reference_wrapper` useful when IMPLICITLY indicating a type with a value =
(maybe with qualifiers), and there are various function templates in the st=
andard library that use this pattern. For example, `std::make_pair`, `std::=
make_typle`, `std::bind`, `std::invoke`, etc. <b>I think it could be a good=
 idea to add handy utilities for implicit type deduction</b>, not only for =
3rd party libary vendor&#39;s convenience, but also to improve the wording =
of these function templates with similar semantics in the standard.</div><d=
iv><br></div><div>For instance, there should be a type template alias (corr=
esponding to `std::decay`, let&#39;s may as well call it `extended_decay`) =
and a function template to forward the parameters (corresponding to `std::f=
orward`, let&#39;s may as well call it `extended_forward`; rvale references=
 are not supported for now). The following code is an implementation for th=
e utilities that is currentely used in my libraries:</div><div><br></div><d=
iv><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250)=
; border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px;=
 word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subprett=
yprint"><font color=3D"#660066"><div class=3D"subprettyprint">namespace det=
ail {</div><div class=3D"subprettyprint"><br></div><div class=3D"subprettyp=
rint">template &lt;class T&gt;</div><div class=3D"subprettyprint">struct re=
ference_wrapper_traits {</div><div class=3D"subprettyprint">=C2=A0 static i=
nline constexpr bool is_reference_wrapper =3D false;</div><div class=3D"sub=
prettyprint">=C2=A0 using dereferenced_type =3D T;</div><div class=3D"subpr=
ettyprint">};</div><div class=3D"subprettyprint"><br></div><div class=3D"su=
bprettyprint">template &lt;class T&gt;</div><div class=3D"subprettyprint">s=
truct reference_wrapper_traits&lt;std::reference_wrapper&lt;T&gt;&gt; {</di=
v><div class=3D"subprettyprint">=C2=A0 static inline constexpr bool is_refe=
rence_wrapper =3D true;</div><div class=3D"subprettyprint">=C2=A0 using der=
eferenced_type =3D T&amp;;</div><div class=3D"subprettyprint">};</div><div =
class=3D"subprettyprint"><br></div><div class=3D"subprettyprint">template &=
lt;class T, bool W&gt;</div><div class=3D"subprettyprint">struct extended_f=
orward_helper;</div><div class=3D"subprettyprint"><br></div><div class=3D"s=
ubprettyprint">template &lt;class T&gt;</div><div class=3D"subprettyprint">=
struct extended_forward_helper&lt;T, false&gt; {</div><div class=3D"subpret=
typrint">=C2=A0 static inline T&amp;&amp; apply(T&amp; t) { return static_c=
ast&lt;T&amp;&amp;&gt;(t); }</div><div class=3D"subprettyprint">};</div><di=
v class=3D"subprettyprint"><br></div><div class=3D"subprettyprint">template=
 &lt;class T&gt;</div><div class=3D"subprettyprint">struct extended_forward=
_helper&lt;T, true&gt; {</div><div class=3D"subprettyprint">=C2=A0 static i=
nline auto apply(T&amp; t)</div><div class=3D"subprettyprint">=C2=A0 =C2=A0=
 =C2=A0 -&gt; typename reference_wrapper_traits&lt;std::decay_t&lt;T&gt;&gt=
;::dereferenced_type</div><div class=3D"subprettyprint">=C2=A0 =C2=A0 =C2=
=A0 { return t.get(); }</div><div class=3D"subprettyprint">};</div><div cla=
ss=3D"subprettyprint"><br></div><div class=3D"subprettyprint">}=C2=A0 // na=
mespace detail</div><div class=3D"subprettyprint"><br></div><div class=3D"s=
ubprettyprint">// This type refers to `std::decay_t&lt;T&gt;`, unless appli=
cation of `std::decay`</div><div class=3D"subprettyprint">// results in `st=
d::reference_wrapper&lt;X&gt;` for some type `X`, in which case the</div><d=
iv class=3D"subprettyprint">// deduced type is `X&amp;`.</div><div class=3D=
"subprettyprint">template &lt;class T&gt;</div><div class=3D"subprettyprint=
">using extended_decay_t =3D typename detail::reference_wrapper_traits&lt;<=
/div><div class=3D"subprettyprint">=C2=A0 =C2=A0 std::decay_t&lt;T&gt;&gt;:=
:dereferenced_type;</div><div class=3D"subprettyprint"><br></div><div class=
=3D"subprettyprint">// This function forwards an lvalue reference to its or=
iginal reference type,</div><div class=3D"subprettyprint">// unless `std::d=
ecay_t&lt;T&gt;` results in `std::reference_wrapper&lt;X&gt;` for some type=
</div><div class=3D"subprettyprint">// `X`, in which case it returns the re=
sult of `value.get()`.</div><div class=3D"subprettyprint">//</div><div clas=
s=3D"subprettyprint">// Note: In case an lvalue reference may be returned, =
it is necessary to</div><div class=3D"subprettyprint">// explicitly announc=
e the return type. Otherwise, there could be an improper</div><div class=3D=
"subprettyprint">// copy construction.</div><div class=3D"subprettyprint">t=
emplate &lt;class T&gt;</div><div class=3D"subprettyprint">auto extended_fo=
rward(std::remove_reference_t&lt;T&gt;&amp; value)</div><div class=3D"subpr=
ettyprint">=C2=A0 =C2=A0 -&gt; std::conditional_t&lt;</div><div class=3D"su=
bprettyprint">=C2=A0 =C2=A0 =C2=A0 =C2=A0 detail::reference_wrapper_traits&=
lt;std::decay_t&lt;T&gt;&gt;::is_reference_wrapper,</div><div class=3D"subp=
rettyprint">=C2=A0 =C2=A0 =C2=A0 =C2=A0 typename detail::reference_wrapper_=
traits&lt;std::decay_t&lt;T&gt;&gt;</div><div class=3D"subprettyprint">=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 ::dereferenced_type, T&amp;&amp;&gt; {</div><div c=
lass=3D"subprettyprint">=C2=A0 return detail::extended_forward_helper&lt;T,=
 detail::reference_wrapper_traits&lt;</div><div class=3D"subprettyprint">=
=C2=A0 =C2=A0 =C2=A0 std::decay_t&lt;T&gt;&gt;::is_reference_wrapper&gt;::a=
pply(value);</div><div class=3D"subprettyprint">}</div></font></div></code>=
</div><br>What do you think of the ideas?</div><div><br></div><div>Mingxin =
Wang</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/2ff776bd-453f-4af1-af45-a16816008a29%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2ff776bd-453f-4af1-af45-a16816008a29=
%40isocpp.org</a>.<br />

------=_Part_1438_47687471.1545795485356--

------=_Part_1437_1567527052.1545795485356--

.
