220 24083 <CADvuK0JeTOPYOp5L79WALmru4gTdHKP+FCPmxo605QAQCs7XmQ@mail.gmail.com> article
Path: news.gmane.org!not-for-mail
From: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Re: RFC: Unpacking tuples to value sequences
Date: Fri, 29 Jan 2016 17:59:19 -0800
Lines: 367
Approved: news@gmane.org
Message-ID: <CADvuK0JeTOPYOp5L79WALmru4gTdHKP+FCPmxo605QAQCs7XmQ@mail.gmail.com>
References: <n7jlvp$c44$1@ger.gmane.org>
	<f758483a-568d-4444-957f-41535c39be4e@isocpp.org>
	<c91a2d40-17da-4edc-b14b-4e166e9ecaeb@isocpp.org>
	<6f3ece34-e302-4d95-afd0-4c1924e8a780@isocpp.org>
	<n7locq$q98$1@ger.gmane.org>
	<e4a9f750-0608-47ac-9d91-f1201b016b99@isocpp.org>
	<n7lqmm$2d3$1@ger.gmane.org>
	<6ad65a24-8a2e-4053-b9c9-80d296d98e7d@isocpp.org>
	<n7m5v9$346$1@ger.gmane.org>
	<72de7daf-93af-4e55-95ea-67898bd2a5f6@isocpp.org>
	<n7o939$vj0$1@ger.gmane.org>
	<CADvuK0+ecVzhSbXo-1Yr-Awp2OGgR53vqe+6oCigA1wS+nVk1w@mail.gmail.com>
	<n7qu59$1sg$1@ger.gmane.org>
	<29e7b2a0-05fb-46e2-92bc-2a83f8a1e53c@isocpp.org>
	<n85baf$hvg$1@ger.gmane.org>
	<CAFk2RUaAbAJPgNZcCBHKEeKO16WTNK2dzHby=8aD1Sra-HpnUA@mail.gmail.com>
	<n85f6j$lh1$1@ger.gmane.org>
	<CAFk2RUbp=SEBZa_T+KUDqOiEt0T-jid4MxkuLJQK=_=_g3pPng@mail.gmail.com>
	<n85lg5$3jl$1@ger.gmane.org>
	<CADvuK0K1frMJcBik1+wV0HXMQX-+YcfF_X8aV9cm20dgNyFcQg@mail.gmail.com>
	<n85upk$71n$1@ger.gmane.org>
	<cd2383c2-e81f-411f-ac71-203ae4398759@isocpp.org>
	<CADvuK0JzXRaw1-m5k0_Lh8O0H9tUoZa3fWVxYuatRABjB_sChA@mail.gmail.com>
	<93bbc0ca-e986-45a3-b86e-9aa4f38feb2e@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary=001a1145b8d8f94465052a837f23
X-Trace: ger.gmane.org 1454119163 31782 80.91.229.3 (30 Jan 2016 01:59:23 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Sat, 30 Jan 2016 01:59:23 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBDLZJYWNDQIPRMNQWUCRUBEFAWWJK@isocpp.org Sat Jan 30 02:59:23 2016
Return-path: <std-proposals+bncBDLZJYWNDQIPRMNQWUCRUBEFAWWJK@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-wm0-f69.google.com ([74.125.82.69])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBDLZJYWNDQIPRMNQWUCRUBEFAWWJK@isocpp.org>)
	id 1aPKos-00043u-BX
	for gclcip-std-proposals@m.gmane.org; Sat, 30 Jan 2016 02:59:22 +0100
Original-Received: by mail-wm0-f69.google.com with SMTP id 128sf879707wmz.0
        for <gclcip-std-proposals@m.gmane.org>; Fri, 29 Jan 2016 17:59:22 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=mime-version:in-reply-to:references:date:message-id:subject:from:to
         :content-type:x-original-sender:x-original-authentication-results
         :reply-to:precedence:mailing-list:list-id:x-spam-checked-in-group
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=lp9IzITsD9981oBZBbhWHMS39uX2phH8Jh7UME6sJug=;
        b=IOvdtsUjSUREUMmPPi/vXYH12yxUWrhrJLeHNw5MGVOqz+ATo42bvcMGHYM8DUY4zy
         MFR8ZWP865WGvTwp53FPokzZHaWAQEjdrF06utVaCw7nfPSuFrpOg1Npwk8T5AyAChU3
         CufASxfzrmABwhiKSkfh8zkKRzYPd/00C0Nx81Mqpz4v84crr0RwwrqArNSyYiEZahpP
         +uO3rJ0ThKFu9Fln/oJzGqzwxbTzbeOpdVLu9K5Sx/A+CwTMvAqtHYN9jSgI5Zn0onJM
         ZmqIE7ucyoGqzSxi99yXJcOXHjFp2oAyAuZfeo7a8fe0ir3m464JXb9uzbe6GkUdTDOL
         +5NQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:mime-version:in-reply-to:references:date
         :message-id:subject:from:to:content-type:x-original-sender
         :x-original-authentication-results:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=lp9IzITsD9981oBZBbhWHMS39uX2phH8Jh7UME6sJug=;
        b=OzEFvj6DXeVxw/NXBxVf+DPQgfgMt7zsBKBhSqD1FUls6AnB0r5mKTH1tST+meg7SB
         vks02VHxYc7ksu59CjLSSM7q7U88lor3km3E39xDpEpqhx6TbA9Sp3fvtHShBvAuCIJZ
         qsnEHA4ndM3dy+aRd7T0yAEsB2vIoe2nxIS5DSaduEUdlkEuk1ffOR93KvhHDDaJ71ni
         SkjUXxaLMpDoJJx0wgtJQFnkTnN6DgMHL+DT0otkL1TBSho9C8yu5A/dLMVM5wgjnb2g
         nSBgoSeGNQX1BCD6YprQHCHwn9nEmLRFvoclo9fA98qOc8cALTCGG1x5oHEImhwVo5NI
         Vb2w==
X-Gm-Message-State: AG10YOS0wsIIows6oB1DyPNVuhLpoKyB+B6AD8v6TGu8930wVgs8JeRmrDocZjw4w2Ohyw==
X-Received: by 10.28.129.210 with SMTP id c201mr32754wmd.1.1454119161784;
        Fri, 29 Jan 2016 17:59:21 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.28.129.6 with SMTP id c6ls159887wmd.4.gmail; Fri, 29 Jan 2016
 17:59:19 -0800 (PST)
X-Received: by 10.28.186.87 with SMTP id k84mr424748wmf.13.1454119159912;
        Fri, 29 Jan 2016 17:59:19 -0800 (PST)
Original-Received: from mail-wm0-x229.google.com (mail-wm0-x229.google.com. [2a00:1450:400c:c09::229])
        by mx.google.com with ESMTPS id mn4si25541922wjc.49.2016.01.29.17.59.19
        for <std-proposals@isocpp.org>
        (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Fri, 29 Jan 2016 17:59:19 -0800 (PST)
Received-SPF: pass (google.com: domain of arthur.j.odwyer@gmail.com designates 2a00:1450:400c:c09::229 as permitted sender) client-ip=2a00:1450:400c:c09::229;
Original-Received: by mail-wm0-x229.google.com with SMTP id p63so2761501wmp.1
        for <std-proposals@isocpp.org>; Fri, 29 Jan 2016 17:59:19 -0800 (PST)
X-Received: by 10.28.19.76 with SMTP id 73mr481707wmt.24.1454119159675; Fri,
 29 Jan 2016 17:59:19 -0800 (PST)
Original-Received: by 10.27.19.201 with HTTP; Fri, 29 Jan 2016 17:59:19 -0800 (PST)
In-Reply-To: <93bbc0ca-e986-45a3-b86e-9aa4f38feb2e@isocpp.org>
X-Original-Sender: arthur.j.odwyer@gmail.com
X-Original-Authentication-Results: mx.google.com;       spf=pass (google.com:
 domain of arthur.j.odwyer@gmail.com designates 2a00:1450:400c:c09::229 as
 permitted sender) smtp.mailfrom=arthur.j.odwyer@gmail.com;       dkim=pass
 header.i=@gmail.com;       dmarc=pass (p=NONE dis=NONE) header.from=gmail.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:24083
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/24083>

--001a1145b8d8f94465052a837f23
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Fri, Jan 29, 2016 at 1:08 PM, Nicol Bolas <jmckesson@gmail.com> wrote:

> On Friday, January 29, 2016 at 2:21:00 PM UTC-5, Arthur O'Dwyer wrote:
>>
>>
>> As of C++11, we have decltype(E) =E2=80=94 which takes the value E and p=
roduces
>> its type =E2=80=94 and we have std::declval<T>() =E2=80=94 which takes a=
 type T and
>> produces a value of that type. And they compose, so I can do a bunch of
>> "value-space" computations and then take the decltype of the resulting
>> expression. Any construct that gets in the way of my doing that is
>> objectionable.
>> In other words, rather than saying that mpl::vector<Ts...> doesn't have
>> a value and so std::get<I>(mplvec) should be ill-formed, I would prefer
>> we simply say that std::get<I>(mplvec) doesn't have a *value* =E2=80=94 =
but it
>> should still have a *type*!
>>
>
> You can want whatever you want, but the fact is that in C++, types and
> values are different things. And we have different mechanisms for dealing
> with each.
>
> Functions take values and return them. Template metafunctions take types
> and can evaluate to types. `declval` doesn't really generate a value in a=
ny
> meaningful way, since it can only exist in a non-evaluated context. And
> while `decltype` does evaluate to a type, that type is not based on a
> value, since the expression itself is never actually evaluated.
>
> Maybe sometimes these things will be equivalent someday. But until then,
> C++ is what it is. Values and types are different, and we shouldn't prete=
nd
> that they're not.
>

That's one point of view, but I tend to think that it's outdated (as of
C++11). We don't need template metafunctions anymore (well, not so many of
them), now that we have constexpr and heterogeneous function templates at
our disposal. For example, where in C++03 we *did* often have to write
template metafunctions such as

*template<class T, class U>*
*struct result_of_plus {*
*    typedef __typeof(T()+U()) type;*
*};*

struct plus {
    template<class T, class U>
    *typename result_of_plus<T,U>::type* operator(T t, U u) { return t + u;
}
};

as of C++14 we no longer need to write any of that metafunction machinery;
we can use decltype to get the compiler to do the meta-lifting on our
behalf, and all we need to worry about are *expressions*, which generally
have both a type and a value.

struct plus {
    template<class T, class U>
    *auto* operator(T t, U u) *-> decltype(t + u)* { return t + u; }
};

(and we don't even need the -> decltype stuff unless we want SFINAE!)
Values and types *are* different, but they are still intimately related
(for example, every value has a type), and while we *can* use different
mechanisms to deal with each, we no longer *need* to.


Having said all that, this "postfix twiddle means std::get<> (and/or
>> std::tuple_element_t<>)" thing still feels too ad-hoc to me.
>>
>
> It's no more ad-hoc than range-based for using `std::begin` and
> `std::end`. You have to have some customization point for user-defined
> types.
>

Agreed, I think, grudgingly, reluctantly, in practice.  In other words, I
agree that's the current state of the world, but I don't *like* it. It
feels much too ad-hoc. begin and end "work" as well as they do because they
had a couple of decades of implementation experience behind them before
people started making up syntactic sugar for them. Right now we have maybe
5 years of experience using std::get and probably even less with
std::tuple_element_t. Are those *exactly* the primitives we want to
syntactic-sugar up, or will we regret the decision in another 5 years when
we realize "how tuples *should* have been done"?

I mean, imagine if instead of iostreams using operator overloading, we had
gotten a syntactic sugar where << in certain contexts expanded to a call to
std::printf(). Makes sense, right? But it would have been horrible for the
flexibility and symmetry of the language as a whole. *And even
iostreams-as-is suck!*  Basically I'm worried that postfix-twiddle and
tuples-as-is are in an analogous situation right now. We might not *want*
to immortalize std::get<I> in language syntax.



> If we could come up with a nice syntax for it, I'd prefer to have the
>> std::get<> written out and just build a simple syntax for getting a
>> parameter-pack of *integer indices*.  I have no idea what that syntax
>> would look like, though, or how it would end up remotely as clean as thi=
s
>> seductive example:
>>
>>     template<class Vec>
>>     auto dotproduct(const Vec& a, const Vec& b)
>>     {
>>         return (... + (a~ * b~));  // this is a C++17 fold-expression
>>     }
>>
>>
> That example seems to be missing what the return value is supposed to be.
> Presumably it's some `Vec` object, but you don't use the typename anywher=
e.
>

The return type is exactly decltype((... + (a~ * b~))). Starting in C++14,
we don't have to write it out; auto suffices for return type deduction.
For example, if Vec is std::tuple<int, double, char>, then decltype((... +
(a~ * b~))) is double.


The only thing I can think to do is to introduce first-class parameter
>> packs, and write
>>
>>     template<size_t I, class... Ts>
>>     auto getp(const std::tuple<Ts...>&) -> Ts...;  // "return a pack"
>>
>>     template<class Vec>
>>     auto dotproduct(const Vec& a, const Vec& b)
>>     {
>>         return (... + (getp(a) * getp(b)));
>>     }
>>
>> But first-class parameter packs seem like a nightmare to specify, don't
>> they?
>>
>
> Um, how exactly is that easier than the user implementing the appropriate
> interfaces? It certainly isn't easier for the reader to understand.
>

My idea was that std::getp would probably be standardized as the "packful"
version of std::get, so the user wouldn't have to actually write out the
implementation of getp in practice.
I agree that the syntax inside this version of dotproduct is much more
off-putting than the postfix-twiddle syntax. *It is uglier.* However,
it is *conceptually
cleaner*, because it doesn't introduce any significantly new grammar (no
postfix-twiddle operator) and it doesn't introduce any new "magic
names" (no hard-coding of the names get and tuple_element_t into the
compiler).  This is a trade-off, and I'm honestly not sure which way would
be better for the language.  It's quite possible (IMHO) that the best
course of action for now would be *not doing either one*.

=E2=80=93Arthur

--=20

---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-propos=
als/.

--001a1145b8d8f94465052a837f23
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Fri, Jan 29, 2016 at 1:08 PM, Nicol Bolas <span dir=3D"=
ltr">&lt;<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson=
@gmail.com</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div class=
=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-l=
eft-style:solid;padding-left:1ex"><div dir=3D"ltr">On Friday, January 29, 2=
016 at 2:21:00 PM UTC-5, Arthur O&#39;Dwyer wrote:<span class=3D""><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wid=
th:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-l=
eft:1ex"><div dir=3D"ltr"><br></div></blockquote><div></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex=
"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>As of C++11, we hav=
e decltype(E) =E2=80=94 which takes the value E and produces its type =E2=
=80=94 and we have std::declval&lt;T&gt;() =E2=80=94 which takes a type T a=
nd produces a value of that type. And they compose, so I can do a bunch of =
&quot;value-space&quot; computations and then take the decltype of the resu=
lting expression. Any construct that gets in the way of my doing that is ob=
jectionable.</div><div>In other words, rather than saying that <font face=
=3D"monospace, monospace">mpl::vector&lt;Ts...&gt;</font> doesn&#39;t have =
a value and so <font face=3D"monospace, monospace">std::get&lt;I&gt;(mplvec=
)</font> should be ill-formed, I would prefer we simply say that <font face=
=3D"monospace, monospace">std::get&lt;I&gt;(mplvec)</font> doesn&#39;t have=
 a <i>value</i> =E2=80=94 but it should still have a <i>type</i>!</div></di=
v></div></div></blockquote></span><div><br>You can want whatever you want, =
but the fact is that in C++, types and=20
values are different things. And we have different mechanisms for=20
dealing with each.<br><br>Functions take values and return them.=20
Template metafunctions take types and can evaluate to types. `declval`=20
doesn&#39;t really generate a value in any meaningful way, since it can onl=
y
 exist in a non-evaluated context. And while `decltype` does evaluate to
 a type, that type is not based on a value, since the expression itself=20
is never actually evaluated.<br><br>Maybe sometimes these things will be
 equivalent someday. But until then, C++ is what it is. Values and types ar=
e=20
different, and we shouldn&#39;t pretend that they&#39;re not.<br></div></di=
v></blockquote><div><br></div><div>That&#39;s one point of view, but I tend=
 to think that it&#39;s outdated (as of C++11). We don&#39;t need template =
metafunctions anymore (well, not so many of them), now that we have constex=
pr and heterogeneous function templates at our disposal. For example, where=
 in C++03 we <i>did</i>=C2=A0often have to write template metafunctions suc=
h as</div><div><br></div><div><b><font face=3D"monospace, monospace">templa=
te&lt;class T, class U&gt;</font></b></div><div><b><font face=3D"monospace,=
 monospace">struct result_of_plus {</font></b></div><div><b><font face=3D"m=
onospace, monospace">=C2=A0 =C2=A0 typedef __typeof(T()+U()) type;</font></=
b></div><div><b><font face=3D"monospace, monospace">};</font></b></div><div=
><font face=3D"monospace, monospace"><br></font></div><div><font face=3D"mo=
nospace, monospace">struct plus {</font></div><div><font face=3D"monospace,=
 monospace">=C2=A0 =C2=A0 template&lt;class T, class U&gt;</font></div><div=
><font face=3D"monospace, monospace">=C2=A0 =C2=A0 <b>typename result_of_pl=
us&lt;T,U&gt;::type</b> operator(T t, U u) { return t + u; }</font></div><d=
iv><font face=3D"monospace, monospace">};</font></div><div><br></div><div>a=
s of C++14 we no longer need to write any of that metafunction machinery; w=
e can use <font face=3D"monospace, monospace">decltype</font>=C2=A0to get t=
he compiler to do the meta-lifting on our behalf, and all we need to worry =
about are <i>expressions</i>, which generally have both a type and a value.=
</div><div><br></div><div><div><font face=3D"monospace, monospace">struct p=
lus {</font></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 te=
mplate&lt;class T, class U&gt;</font></div><div><font face=3D"monospace, mo=
nospace">=C2=A0 =C2=A0=C2=A0<b>auto</b>=C2=A0operator(T t, U u) <b>-&gt; de=
cltype(t + u)</b> { return t + u; }</font></div><div><font face=3D"monospac=
e, monospace">};</font></div></div><div><font face=3D"monospace, monospace"=
><br></font></div><div>(and we don&#39;t even need the <font face=3D"monosp=
ace, monospace">-&gt; decltype</font> stuff unless we want SFINAE!)</div><d=
iv>Values and types <i>are</i> different, but they are still intimately rel=
ated (for example, every value has a type), and while we <i>can</i> use dif=
ferent mechanisms to deal with each, we no longer <i>need</i> to.</div><div=
><br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin=
:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204)=
;border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"=
"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;borde=
r-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid=
;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>Ha=
ving said all that, this &quot;postfix twiddle means std::get&lt;&gt; (and/=
or std::tuple_element_t&lt;&gt;)&quot; thing still feels too ad-hoc to me.<=
/div></div></div></div></blockquote></span><div><br>It&#39;s no more ad-hoc=
 than range-based for using `std::begin` and `std::end`. You have to have s=
ome customization point for user-defined types.<br></div></div></blockquote=
><div><br></div><div>Agreed, I think, grudgingly, reluctantly, in practice.=
=C2=A0 In other words, I agree that&#39;s the current state of the world, b=
ut I don&#39;t <i>like</i> it. It feels much too ad-hoc. begin and end &quo=
t;work&quot; as well as they do because they had a couple of decades of imp=
lementation experience behind them before people started making up syntacti=
c sugar for them. Right now we have maybe 5 years of experience using std::=
get and probably even less with std::tuple_element_t. Are those <i>exactly<=
/i> the primitives we want to syntactic-sugar up, or will we regret the dec=
ision in another 5 years when we realize &quot;how tuples <i>should</i> hav=
e been done&quot;?</div><div><br></div><div>I mean, imagine if instead of i=
ostreams using operator overloading, we had gotten a syntactic sugar where =
<font face=3D"monospace, monospace">&lt;&lt;</font> in certain contexts exp=
anded to a call to <font face=3D"monospace, monospace">std::printf()</font>=
.. Makes sense, right? But it would have been horrible for the flexibility a=
nd symmetry of the language as a whole. <i>And even iostreams-as-is suck!</=
i> =C2=A0Basically I&#39;m worried that postfix-twiddle and tuples-as-is ar=
e in an analogous situation right now. We might not <i>want</i> to immortal=
ize <font face=3D"monospace, monospace">std::get&lt;I&gt;</font> in languag=
e syntax.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_q=
uote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-c=
olor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D=
"ltr"><span class=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bo=
rder-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D=
"gmail_quote"><div>If we could come up with a nice syntax for it, I&#39;d p=
refer to have the std::get&lt;&gt; written out and just build a simple synt=
ax for getting a parameter-pack of <i>integer indices</i>.=C2=A0 I have no =
idea what that syntax would look like, though, or how it would end up remot=
ely as clean as this seductive example:</div><div><br></div><div><div style=
=3D"font-size:13px"><span style=3D"font-family:monospace,monospace">=C2=A0 =
=C2=A0 template&lt;class Vec&gt;</span><br></div><div style=3D"font-size:13=
px"><font face=3D"monospace, monospace">=C2=A0 =C2=A0 auto dotproduct(const=
 Vec&amp; a, const Vec&amp; b)</font></div><div style=3D"font-size:13px"><f=
ont face=3D"monospace, monospace">=C2=A0 =C2=A0 {</font></div><div style=3D=
"font-size:13px"><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 return (... + (a~ * b~)); =C2=A0// this is a C++17 fold-expression</=
font></div><div style=3D"font-size:13px"><font face=3D"monospace, monospace=
">=C2=A0 =C2=A0 }</font></div></div><div><br></div></div></div></div></bloc=
kquote></span><div><br>That example seems to be missing what the return val=
ue is supposed to be. Presumably it&#39;s some `Vec` object, but you don&#3=
9;t use the typename anywhere.<br></div></div></blockquote><div><br></div><=
div>The return type is exactly <font face=3D"monospace, monospace">decltype=
((... + (a~ * b~)))</font>. Starting in C++14, we don&#39;t have to write i=
t out; <font face=3D"monospace, monospace">auto</font> suffices for return =
type deduction.</div><div>For example, if <font face=3D"monospace, monospac=
e">Vec</font> is <font face=3D"monospace, monospace">std::tuple&lt;int, dou=
ble, char&gt;</font>, then=C2=A0<span style=3D"font-family:monospace,monosp=
ace">decltype((... + (a~ * b~)))</span>=C2=A0is <font face=3D"monospace, mo=
nospace">double</font>.</div><div><br></div><div><br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;b=
order-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"=
><div dir=3D"ltr"><span class=3D""><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>=
<div class=3D"gmail_quote"><div>The only thing I can think to do is to intr=
oduce first-class parameter packs, and write</div><div><br></div><div><div>=
<div style=3D"font-size:13px"><span style=3D"font-family:monospace,monospac=
e">=C2=A0 =C2=A0 template&lt;size_t I, class... Ts&gt;</span><br></div><div=
 style=3D"font-size:13px"><font face=3D"monospace, monospace">=C2=A0 =C2=A0=
 auto getp(const std::tuple&lt;Ts...&gt;&amp;) -&gt; Ts...; =C2=A0// &quot;=
return a pack&quot;</font></div><div style=3D"font-size:13px"><span style=
=3D"font-family:monospace,monospace"><br></span></div><div style=3D"font-si=
ze:13px"><span style=3D"font-family:monospace,monospace">=C2=A0 =C2=A0 temp=
late&lt;class Vec&gt;</span><br></div><div style=3D"font-size:13px"><font f=
ace=3D"monospace, monospace">=C2=A0 =C2=A0 auto dotproduct(const Vec&amp; a=
, const Vec&amp; b)</font></div><div style=3D"font-size:13px"><font face=3D=
"monospace, monospace">=C2=A0 =C2=A0 {</font></div><div style=3D"font-size:=
13px"><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 retur=
n (... + (getp(a) * getp(b)));</font></div><div style=3D"font-size:13px"><f=
ont face=3D"monospace, monospace">=C2=A0 =C2=A0 }</font></div></div></div><=
div><br></div><div>But first-class parameter packs seem like a nightmare to=
 specify, don&#39;t they?</div></div></div></div></blockquote></span><div><=
br>Um, how exactly is that easier than the user implementing the appropriat=
e interfaces? It certainly isn&#39;t easier for the reader to understand.</=
div></div></blockquote><div><br></div><div>My idea was that <font face=3D"m=
onospace, monospace">std::getp</font> would probably be standardized as the=
 &quot;packful&quot; version of <font face=3D"monospace, monospace">std::ge=
t</font>, so the user wouldn&#39;t have to actually write out the implement=
ation of <font face=3D"monospace, monospace">getp</font> in practice.</div>=
<div>I agree that the syntax inside this version of <font face=3D"monospace=
, monospace">dotproduct</font> is much more off-putting than the postfix-tw=
iddle syntax. <b>It is uglier.</b> However, it is <b>conceptually cleaner</=
b>, because it doesn&#39;t introduce any significantly new grammar (no post=
fix-twiddle operator) and it doesn&#39;t introduce any new &quot;magic name=
s&quot;=C2=A0(no hard-coding of the names=C2=A0<font face=3D"monospace, mon=
ospace">get</font>=C2=A0and=C2=A0<font face=3D"monospace, monospace">tuple_=
element_t</font>=C2=A0into the compiler).=C2=A0 This is a trade-off, and I&=
#39;m honestly not sure which way would be better for the language.=C2=A0 I=
t&#39;s quite possible (IMHO) that the best course of action for now would =
be=C2=A0<b>not doing either one</b>.</div><div><br></div><div>=E2=80=93Arth=
ur</div></div></div></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"https://groups.google.com/a/isocpp.org/group=
/std-proposals/">https://groups.google.com/a/isocpp.org/group/std-proposals=
/</a>.<br />

--001a1145b8d8f94465052a837f23--

.
