<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<title>Structured bindings with explicit types</title>

	<style>
	p {text-align:justify}
	li {text-align:justify}
	blockquote.note
	{
		background-color:#E0E0E0;
		padding-left: 15px;
		padding-right: 15px;
		padding-top: 1px;
		padding-bottom: 1px;
	}
	ins {color:#00A000}
	del {color:#A00000}
	</style>
</head>
<body>

<address align=right>
Document number: P0480R1
<br/>
Audience: EWG
<br/>
<br/>
<a href="mailto:ville.voutilainen@gmail.com">Ville Voutilainen</a><br/>
2018-10-08<br/>
</address>
<hr/>
<h1 align=center>Structured bindings with explicit types</h1>

<h2>Abstract</h2>

<p>Here's the tl;dr: allow
<pre><blockquote><code> auto [std::string a, int b] = f();
</code></blockquote></pre>	
</p>

<h2>Rationale</h2>

<p>
  C++ allows explicit and non-deduced typing to be used at API boundaries
  when that's deemed the right choice. This is one of the biggest
  strenghts of C++; when users opt in to an explicit type, incompatible
  API changes will break code loudly, and a compiler will tell a user
  what places to fix when an API refactoring occurs.
</p>

<p>
  Structured bindings don't allow such an explicit typing to occur;
  yet it seems very plausible that sometimes structured bindings are
  used at such API boundaries. Therefore we should allow making the types
  of the bindings concrete and explicit, not just deduced.
</p>


<h2>"But bindings must be bindings, not new variables..."</h2>

<p>
  They are. The rule must be that, regardless of whether we allow any
  conversions, that new objects are never created by the bindings.
</p>

<h2>"Conversions?"</h2>

<p>
  Well. For the most important use cases, being able to
  specify the exact type of a binding is already a big
  help. However, it seems like we can and perhaps should allow
  some conversions, like derived-to-base and qualification conversions.
  That is,
  <pre><blockquote><code>struct B {}; struct D : B {};
struct X {D a; D b;};
auto [D x, D y] = X(); // this should be relatively non-controversial
auto [B x, B y] = X(); // this seems reasonable
auto [const D x, const D y] = X(); // this seems very reasonable
auto [const B x, const B y] = X(); // this seems reasonable
  </code></blockquote></pre>
  As background material, Gabriel Dos Reis recommended looking
  at <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1782.pdf">N1782</a>, especially sections 6.7 and 7.*.
</p>

<h2>"If we allow conversions, what's the decltype of the binding?"</h2>

<p>
  In the above example, if the type of the thing to bind is
  D and we convert to B, I'd expect the decltype of the binding to
  be B. If the type of the thing to bind is D& and we convert to
  B, I'd expect the decltype of the binding to be B&. That is,
  convert the non-reference type (again, without creating a new
  object), and then reflect the tuple_element's type (reference
  or non-reference) in the result.
</p>

<h2>"Has this been implemented?"</h2>

<p>No.</p>

<h2>"Does this need to go into C++20?"</h2>

<p>Yes. The sooner the better. The current forcing of
  using deduction and only deduction with structured
  bindings causes long-term harm, because it prevents
  writing concretely-typed API boundaries from the client
  side of structured bindings. Separate static_asserts
  to assert a type of a binding are antithetical.
</p>
<p>
  I did say that I need to implement this proposal before
  it becomes C++20 material. That implementation is pending,
  but I am going to propose this anyway so that it has a chance
  to get in.
</p>

<h2>"Should it be possible to specify the type of the whole-object?"</h2>

<p>
  As in "ConcreteType [a, b] = f()", that doesn't seem to be necessary.
  If I use structured bindings, the types of the bindings are what
  matters in a strong/concrete API boundary, the whole-object
  type is irrelevant. If I don't use structured bindings, I can already
  use concrete types.
</p>

<h2>"Should lambda captures also allow specifying types?"</h2>

<p>
  As in "[std::string a = f()]{...}" or even "[std::string x]{...}",
  well, that would probably be useful. If this proposal is accepted,
  lambdas are the last place where a concrete type cannot be specified.
  The snag there is that a by-value capture will create a new object,
  so it allows more conversions. The syntaxes end up looking the
  same but doing different things (which is not new, though, the
  current syntax of lambda captures and structured bindings looks
  the same but does vastly different things).
</p>
</body>

</html>
