220 23831 <n7jlvp$c44$1@ger.gmane.org> article
Path: news.gmane.org!not-for-mail
From: Matthew Woehlke <mwoehlke.floss@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: RFC: Unpacking tuples to value sequences
Date: Mon, 18 Jan 2016 16:38:01 -0500
Lines: 324
Approved: news@gmane.org
Message-ID: <n7jlvp$c44$1@ger.gmane.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed;
 boundary="------------040701080604080000030303"
X-Trace: ger.gmane.org 1453153101 15393 80.91.229.3 (18 Jan 2016 21:38:21 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Mon, 18 Jan 2016 21:38:21 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBC37LBFWUIFBBQNW6W2AKGQETZV4RAI@isocpp.org Mon Jan 18 22:38:13 2016
Return-path: <std-proposals+bncBC37LBFWUIFBBQNW6W2AKGQETZV4RAI@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-wm0-f70.google.com ([74.125.82.70])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBC37LBFWUIFBBQNW6W2AKGQETZV4RAI@isocpp.org>)
	id 1aLHV5-00031a-ID
	for gclcip-std-proposals@m.gmane.org; Mon, 18 Jan 2016 22:38:11 +0100
Original-Received: by mail-wm0-f70.google.com with SMTP id b14sf32794249wmb.2
        for <gclcip-std-proposals@m.gmane.org>; Mon, 18 Jan 2016 13:38:11 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=to:from:subject:date:lines:message-id:mime-version:content-type
         :user-agent: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=MtfIe+w8djU4Al3L9rb1EIF3PmTHAjUYnlZN49m/8Ok=;
        b=pFM0Nt1yvWpV2YKleLddJdefm7UsBlRzRmG5K6T+NbmzRkUmSUvLKavLrLuQO1XREJ
         Q8vygglhqAR0s6i8InRjjQrjY/qFWj/s3ToLkbwMFKjJPYdhvq/PJDbDU2JunEcL9f74
         bW3d2t7NsQDLWVbzIIzq/3RTnDHEaJo6c69q37w/8LQhyJPHGa1zljkTXfWRfBTCPxNT
         EmJaxgR4FchLTKizLxooX0ly3oKM8nP/Cxlezjs3+MoidkbxgIZOuS/D6FfDPeTvF/KF
         +HvcQVZKVvwbN4u8TtGkQSZRlQ4CFEEmtXgJ24cUWCunecUv29CZeiVRnnzSbwt9FAl0
         cZ0Q==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:to:from:subject:date:lines:message-id
         :mime-version:content-type:user-agent: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=MtfIe+w8djU4Al3L9rb1EIF3PmTHAjUYnlZN49m/8Ok=;
        b=VZqz9sodpyPZZhr1SP/EEk5qCdJfrsc8bAaRbHTEfa+pUK9qGEjUvNLI9Uk4jnWYXe
         xObkQhrvMLzNYRZgVvcJQj+saWV5GaHMK1VO2KNeiNBn7qAZzq9+/yWF3fbupMxe+/C1
         eH3iI9e3Fe9CJquh1E+mx+mRTV8pHNsq9hjX3CxEkVR3C1kjgmP6HcUe3OuWo2jzJnqi
         6YcfvP7rzEPMdSX3gMc6hRmi27cWzTlwb6hEqWjjo98iVG5IZGW/lPDbfFWeIKJajQct
         RsyMeVMYu2DI8cI32KiQ1g0kLthTWWYeBtPkWC6pQk0S1IEniy9LanegCU3Je2t+lpX9
         7xDQ==
X-Gm-Message-State: ALoCoQlaxSCpz3UCwMu1DuxXcjmaH6ZZDsyA2wb52kt3d6eijQJrNOK/DbEKeNN+bgaoVfgwrbZQ0h7hdtGPGadhtftYz5zPqg==
X-Received: by 10.112.132.74 with SMTP id os10mr3414300lbb.22.1453153091122;
        Mon, 18 Jan 2016 13:38:11 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.25.91.75 with SMTP id p72ls390424lfb.28.gmail; Mon, 18 Jan
 2016 13:38:08 -0800 (PST)
X-Received: by 10.112.140.41 with SMTP id rd9mr9538308lbb.138.1453153088550;
        Mon, 18 Jan 2016 13:38:08 -0800 (PST)
Original-Received: from plane.gmane.org (plane.gmane.org. [80.91.229.3])
        by mx.google.com with ESMTPS id m67si13152548lfb.89.2016.01.18.13.38.08
        for <std-proposals@isocpp.org>
        (version=TLS1 cipher=AES128-SHA bits=128/128);
        Mon, 18 Jan 2016 13:38:08 -0800 (PST)
Received-SPF: pass (google.com: domain of gclcip-std-proposals@m.gmane.org designates 80.91.229.3 as permitted sender) client-ip=80.91.229.3;
Original-Received: from list by plane.gmane.org with local (Exim 4.69)
	(envelope-from <gclcip-std-proposals@m.gmane.org>)
	id 1aLHV1-0002xT-HY
	for std-proposals@isocpp.org; Mon, 18 Jan 2016 22:38:07 +0100
Original-Received: from tripoint.kitware.com ([66.194.253.20])
        by main.gmane.org with esmtp (Gmexim 0.1 (Debian))
        id 1AlnuQ-0007hv-00
        for <std-proposals@isocpp.org>; Mon, 18 Jan 2016 22:38:07 +0100
Original-Received: from mwoehlke.floss by tripoint.kitware.com with local (Gmexim 0.1 (Debian))
        id 1AlnuQ-0007hv-00
        for <std-proposals@isocpp.org>; Mon, 18 Jan 2016 22:38:07 +0100
X-Injected-Via-Gmane: http://gmane.org/
Original-Lines: 315
Original-X-Complaints-To: usenet@ger.gmane.org
X-Gmane-NNTP-Posting-Host: tripoint.kitware.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0
X-Original-Sender: mwoehlke.floss@gmail.com
X-Original-Authentication-Results: mx.google.com;       spf=pass (google.com:
 domain of gclcip-std-proposals@m.gmane.org designates 80.91.229.3 as
 permitted sender) smtp.mailfrom=gclcip-std-proposals@m.gmane.org;
       dmarc=fail (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:23831
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/23831>

This is a multi-part message in MIME format.
--------------040701080604080000030303
Content-Type: text/plain; charset=UTF-8

Okay, after Vicente convinced me I should write this, I present to you
the start of a paper proposing a '[*]' operator (not pushed yet, and
just .rst for now; sorry).

The general gist is:

  struct Datum { int id; double value; };

  auto d1 = Datum{42, 2.7};
  auto d2 = Datum{[*]d1};
  foo([*]d1, [*]d2);

  // equivalent to:
  auto d2 = Datum{get<0>(d1), get<1>(d2)};
  foo(get<0>(d1), get<1>(d1), get<0>(d2), get<1>(d2));

(Yes, the first case is silly; it's more interesting if instead of a
Datum in both cases, the second was a different but layout-compatible
type. The paper has a somewhat better version of the example.)

As described in the paper, there is at least one use case for this
language feature that cannot be (easily) accomplished otherwise:

  template <type T>
  foo(T const& tuple_like)
  {
    new Bar{next_id(), [*]tuple_like};
  }

If Bar cannot take a T directly (e.g. because it is an external library
type), but the 'tuple size' of T is not known, it is impossible to write
a single generic definition of foo() (and hard, or at least very
annoying, to write specializations).

I haven't written a proposed wording yet, and not sure if I will be able
to until "tuple like" is specified. (BTW, is there an official paper on
that yet?)

Comments, as always, welcome. Motivating use cases especially welcome :-).

-- 
Matthew

-- 

--- 
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.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-proposals/.

--------------040701080604080000030303
Content-Type: text/prs.fallenstein.rst;
 name="PXXXX Value Sequence Unpacking.rst"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
 filename="PXXXX Value Sequence Unpacking.rst"

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
  Value Sequence Unpacking
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D

:Document:  PXXXX (TBD)
:Date:      2016-01-15
:Author:    Matthew Woehlke (mwoehlke.floss@gmail.com)

=2E. raw:: html

  <style>
    html { color: black; background: white; }
  </style>


Abstract
=3D=3D=3D=3D=3D=3D=3D=3D

This proposal describes a new language feature which allows tuple-like ob=
jects to be "unpacked" into a value sequence.

(Note: references made to the existing draft standard are made against N4=
567_.)

=2E. contents::


Rationale
=3D=3D=3D=3D=3D=3D=3D=3D=3D

There is an increasing push in C++ to add interoperability between values=
 and value sequences, exemplified by the recent addition of ``std::tuple`=
` and proposals such as P0144_ / P0151_, the anticipated proposal for ext=
ending the concept of "tuple-like" to arbitrary types, the existing ``std=
::experimental::apply``, and the anticipated and competing proposal to ad=
d a library based ``std::unpack`` function and corresponding ``std::unpac=
ked`` type. Similar features have long been present in other languages, w=
ith Python frequently held up as a representative example.

While we feel that P0144_ / P0151_ represent an important step in the rig=
ht direction, these proposals address only one of two facets of "unpackin=
g"; namely, unpacking as part of variable assignment. The problem of how =
to unpack a tuple-like in other contexts remains to be addressed. Possibl=
e contexts include:

=2E. code:: c++

  auto t =3D get_tuple_like();

  int a[] =3D {t...};
  auto b =3D Bar{t...};
  foo(t...);
  return {t...};

The existing ``std::experimental::apply`` is only capable of addressing t=
he third example, and only in the limited case that the tuple is exactly =
the set of arguments to be passed. The competing ``std::unpack`` proposal=
 would address the second limitation, but cannot address the first.

(The problem of what exactly constitutes a "tuple-like" also remains to b=
e addressed. However, we feel that this is out of scope for this proposal=
, and anticipate a separate proposal covering this issue.)

The ability to unpack a tuple-like into a value sequence raises many inte=
resting possibilities, but especially a degree of type amorphism. For exa=
mple, one complaint levied against PXXXX_ is that it provides no mechanis=
m for implicit conversion between different but layout-compatible aggrega=
tes. As discussed in that proposal, we believe that such an *implicit* me=
chanism would be wrong, but the lack of even an *explicit* mechanism repr=
esents an understandable reservation. Unpacking (and generalized support =
for tuple-like entities) would trivially provide such a mechanism:

=2E. code:: c++

  struct Foo { int id; double value; };
  struct Bar { int identifier; double numeric_value; };

  Foo f =3D foo();
  auto b =3D Bar{[*]f};

  // ...or even
  auto b =3D Bar{[*]foo()};

Other possibilities include trivially deserializing arguments to RPC's or=
 using ``std::any`` to type-erase a variadic argument list through part o=
f a complex call chain.

One use case that demands special attention relates to generic code. Cons=
ider a problem such as:

=2E. code:: c++

  template <typename T>
  void foo(T const& tuple_like)
  {
    bar(...); // unpack tuple_like into arguments to bar()
  }

The obvious problem here is that we do not know the "tuple size" of ``tup=
le_like``, so we cannot simply write out a list of ``get<N>(tuple_like)``=
 calls. While it may be possible here, in this simple case, to use ``std:=
:experimental::apply``, this breaks down almost immediately if the contex=
t into which we need to unpack ``tuple_like`` differs (see previous comme=
nts). While we believe it is theoretically possible to resolve this issue=
 by partially specializing on the "tuple size" of ``T``, this becomes ext=
remely awkward and verbose almost immediately, not to mention the copious=
 amounts of duplicated code.


Proposal
=3D=3D=3D=3D=3D=3D=3D=3D

We propose to add a language feature to perform unpacking in non-assignme=
nt contexts. This would conceptually be a code transformation or "syntax =
sugar", meaning that it does not allow us to do anything truly novel (alt=
hough unpacking a template-parameter type comes very close), but greatly =
simplifies the amount of code that must be written for common cases. Spec=
ifically, we propose to introduce a new prefix operator ``[*]`` which sha=
ll instruct the compiler to unpack a tuple-like "in place". For example:

=2E. code:: c++

  std::tuple<int, double> foo();
  bar(int, int, double);

  bar(42, [*]foo());

This would be equivalent to:

=2E. code:: c++

  auto&& __t =3D foo(); // compiler-internal temporary
  bar(42, get<0>(__t), get<1>(__t));

This would allow unpacking to be performed in any context where a ``,``-s=
eparated sequence of expressions is accepted:

=2E. code:: c++

  // Let t1, t2, etc. be functions returning tuples

  // Constructor arguments
  auto b =3D bar{[*]t1()};

  // Function arguments
  // Note unpacking of multiple tuples mixed with single arguments
  foo(1, 15, [*]t2(), "hello", [*]t3(), 3.14159);

  // Initializer list
  int arr[] =3D {[*]t4()};

  // Return with elided type
  return {[*]t5()};


Proposed Wording
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

=2E. TODO


Discussion
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

What syntax should be used?
---------------------------

Astute readers will notice that different syntax was used in the Rational=
e_ section than has been proposed. To some extent, we feel that the exact=
 syntax is less important than the feature as a whole. However, there are=
 a few reasons why we prefer the proposed syntax to an alternative such a=
s a trailing ``...`` operator. First, there is the potential for ambiguit=
y with "unpacking" as it relates to template argument packs, which are no=
t quite the same as tuple-like objects. Second, as noted in `Future Direc=
tions`_, we anticipate the eventual desire to be able to slice the object=
 being unpacked; addition of such syntax fits naturally with the proposed=
 syntax, but would be more difficult with ``...``. That being said, we re=
cognize that other syntaxes may be possible and equally desirable, and ar=
e open to revision in this respect.

What about a library solution?
------------------------------

As previously mentioned, we anticipate presentation of a competing propos=
al (not yet available at time of writing) providing a library-only soluti=
on to unpacking in the context of ``std::invoke``. This proposal would in=
troduce the helper ``std::unpack`` which transforms a tuple-like into a c=
orresponding type ``std::unpacked``. The problem, as we see it, with this=
 proposal is two-fold. First, the creation of an actual type raises the p=
ossibility of ambiguity; is a ``std::unpacked`` meant to be treated as a =
value sequence, or as a single container-like object? Second, and more cr=
itical, is that a library solution is vastly more limited. For instance, =
it is not possible (without resorting to some form of indirection, such a=
s ``std::invoke``) to call legacy functions with an unpacked tuple-like. =
Second, such a proposal would, at best, require complicated specification=
 of how an unpacked tuple-like is to be used in certain special contexts,=
 such as initializer lists or constructor parameters.

A language feature, implemented as a compile-time code transformation (si=
milar to range-based for), does not have these limitations. The proposed =
language feature is usable in any context where a value sequence is accep=
ted, including argument lists and initializer lists. Also, because it *is=
* a code transform, there is no "magic type" where ambiguity of intent mi=
ght be introduced.


Future Directions
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Python supports array slicing. It seems clearly desirable that at some po=
int a tuple slicing mechanism should be added to C++ as well. While there=
 will invariably be cases where slicing must be done at run-time where a =
library solution is the best answer, creating a library solution that can=
 be evaluated at compile-time in order to use sliced tuple-likes for unpa=
cking may prove difficult. It may therefore be desirable to extend the pr=
oposed feature to include slicing support, e.g.:

=2E. code:: c++

  auto t =3D get_tuple_like();
  foo([1]t); // foo(get<1>(t));
  foo([1:3]t); // foo(get<1>(t), get<2>(t));

This could even be expanded beyond Python's modest support to allow for c=
omplex slicing and even rearranging of values:

=2E. code:: c++

  foo([1,5:7,2]t); // foo(get<1>(t), get<5>(t), get<6>(t), get<2>(t));


Acknowledgments
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

We wish to thank everyone on the ``std-proposals`` forum that has contrib=
uted (unfortunately, this idea has been marinating for a long time, and w=
e would have difficulty identifying again everyone who has contributed in=
 the past). More recently, we wish to thank Vicente J. Botet Escriba for =
submitting a competing proposal and therefore providing the motivation to=
 turn our idea into a concrete proposal.

=2E. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..=
 .. ..

=2E. _N4560: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n456=
0.pdf
=2E. _N4567: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n456=
7.pdf
=2E. _P0144: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p014=
4r0.pdf
=2E. _P0151: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p015=
1r0.pdf

=2E. TODO proper link to anonymous struct proposal (PXXXX)

=2E. |--| unicode:: U+02014 .. em dash

--------------040701080604080000030303--


.
