Topic: static if resurrected (N4461) and type-generic expressions


Author: David Krauss <potswa@gmail.com>
Date: Fri, 17 Apr 2015 23:10:16 +0800
Raw View
--Apple-Mail=_B5615A44-2992-49DE-82C6-B83654777091
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8

I think an expression-level facility would nicely complement N4461. The res=
urrected static if (or static_if) is much more sane and tractable. It leave=
s out one use-case, though: type-dependent variables and expressions.

We already have type-dependent variables, of course, but only when the decl=
ared type of the variable is covariant with the initializing expression. If=
 it=E2=80=99s impossible to write a generic initializer, then an overload s=
et is needed. Likewise with expressions that aren=E2=80=99t initializing a =
variable. The ternary operator falls short.

The problem with the original static if is that declarations can be complet=
ely hidden, such that a name might or might not be declared in the enclosin=
g scope. But variables that are conditionally needed might as well be =E2=
=80=9Cneutered=E2=80=9D without being completely eliminated, name and all.

C11 type-generic expressions already provide for selecting between expressi=
ons with different types, much like N4461 but with expression-level granula=
rity instead of statement-level. Lambdas can actually implement either (rou=
ghly) in terms of the other:

#define UNPAREN( ... ) __VA_ARGS__
#define static_if( CONDITION, IF, ELSE ) \
    ((void) _Generic( std::bool_constant< CONDITION >{}, \
        std::true_type: []{ UNPAREN IF }(), \
        std::false_type: []{ UNPAREN ELSE }() ) \
    ))

#define _Generic( EXPR, TYPE, IF, ELSE ) \
    ([&]{
        static if ( std::is_same_v< decltype( EXPR ), TYPE > ) {
            return IF;
        } static else {
            return ELSE;
        }
    }())

TGEs aren=E2=80=99t offered in any C++ implementation, as far as I know, be=
cause:

1. The C standard doesn=E2=80=99t constrain the unused expressions as C++ t=
emplates would need.
2. C++ programmers don=E2=80=99t really want to switch on type-ids, but on =
Boolean expressions instead.

These issues should be fixable:

1. Only let TGEs appear in templates. (Apply the same constraints as static=
 if.)
2. Allow Boolean (or other integer) conditions. Two alternatives:
2a. If the controlling expression is not type-dependent, interpret it, and =
the =E2=80=9Clabels,=E2=80=9D as integral constant expressions.
2b. Let the operator be called something other than _Generic.

--=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 http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--Apple-Mail=_B5615A44-2992-49DE-82C6-B83654777091
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D"">I think an express=
ion-level facility would nicely complement N4461. The resurrected&nbsp;<fon=
t face=3D"Courier" class=3D"">static if</font> (or&nbsp;<font face=3D"Couri=
er" class=3D"">static_if</font>) is much more sane and tractable. It leaves=
 out one use-case, though: type-dependent variables and expressions.<div cl=
ass=3D""><div class=3D""><br class=3D""></div><div class=3D"">We already ha=
ve type-dependent variables, of course, but only when the declared type of =
the variable is covariant with the initializing expression. If it=E2=80=99s=
 impossible to write a generic initializer, then an overload set is needed.=
 Likewise with expressions that aren=E2=80=99t initializing a variable. The=
 ternary operator falls short.</div><div class=3D""><br class=3D""></div><d=
iv class=3D"">The problem with the original&nbsp;<span style=3D"font-family=
: Courier;" class=3D"">static if</span>&nbsp;is that declarations can be co=
mpletely hidden, such that a name might or might not be declared in the enc=
losing scope. But variables that are conditionally needed might as well be =
=E2=80=9Cneutered=E2=80=9D without being completely eliminated, name and al=
l.</div><div class=3D""><br class=3D""></div><div class=3D"">C11 type-gener=
ic expressions already provide for selecting between expressions with diffe=
rent types, much like N4461 but with expression-level granularity instead o=
f statement-level. Lambdas can actually implement either (roughly) in terms=
 of the other:</div><div class=3D""><br class=3D""></div><div class=3D""><f=
ont face=3D"Courier" class=3D"">#define UNPAREN( ... ) __VA_ARGS__</font></=
div><div class=3D""><font face=3D"Courier" class=3D"">#define static_if( CO=
NDITION, IF, ELSE ) \</font></div><div class=3D""><font face=3D"Courier" cl=
ass=3D"">&nbsp; &nbsp; ((void) _Generic( std::bool_constant&lt; CONDITION &=
gt;{}, \</font></div><div class=3D""><font face=3D"Courier" class=3D"">&nbs=
p; &nbsp; &nbsp; &nbsp; std::true_type: []{ UNPAREN IF }(), \</font></div><=
div class=3D""><font face=3D"Courier" class=3D"">&nbsp; &nbsp; &nbsp; &nbsp=
; std::false_type: []{ UNPAREN ELSE }() ) \</font></div><div class=3D""><fo=
nt face=3D"Courier" class=3D"">&nbsp; &nbsp; ))</font></div><div class=3D""=
><font face=3D"Courier" class=3D""><br class=3D""></font></div><div class=
=3D""><font face=3D"Courier" class=3D"">#define _Generic( EXPR, TYPE, IF, E=
LSE ) \</font></div><div class=3D""><font face=3D"Courier" class=3D"">&nbsp=
; &nbsp; ([&amp;]{</font></div><div class=3D""><font face=3D"Courier" class=
=3D"">&nbsp; &nbsp; &nbsp; &nbsp; static if ( std::is_same_v&lt; decltype( =
EXPR ), TYPE &gt; ) {</font></div><div class=3D""><font face=3D"Courier" cl=
ass=3D"">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return IF;</font></div><=
div class=3D""><font face=3D"Courier" class=3D"">&nbsp; &nbsp; &nbsp; &nbsp=
; } static else {</font></div><div class=3D""><font face=3D"Courier" class=
=3D"">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return ELSE;</font></div><d=
iv class=3D""><font face=3D"Courier" class=3D"">&nbsp; &nbsp; &nbsp; &nbsp;=
 }</font></div><div class=3D""><font face=3D"Courier" class=3D"">&nbsp; &nb=
sp; }())</font></div><div class=3D""><br class=3D""></div><div class=3D"">T=
GEs aren=E2=80=99t offered in any C++ implementation, as far as I know, bec=
ause:</div><div class=3D""><br class=3D""></div><div class=3D"">1. The C st=
andard doesn=E2=80=99t constrain the unused expressions as C++ templates wo=
uld need.</div><div class=3D"">2. C++ programmers don=E2=80=99t really want=
 to switch on type-ids, but on Boolean expressions instead.</div><div class=
=3D""><br class=3D""></div><div class=3D"">These issues should be fixable:<=
/div><div class=3D""><br class=3D""></div><div class=3D"">1. Only let TGEs =
appear in templates. (Apply the same constraints as&nbsp;<span style=3D"fon=
t-family: Courier;" class=3D"">static if</span>.)</div><div class=3D"">2. A=
llow Boolean (or other integer) conditions. Two alternatives:</div><div cla=
ss=3D"">2a. If the controlling expression is not type-dependent, interpret =
it, and the =E2=80=9Clabels,=E2=80=9D as integral constant expressions.</di=
v><div class=3D"">2b. Let the operator be called something other than <font=
 face=3D"Courier" class=3D"">_Generic</font>.</div></div></body></html>

<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"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--Apple-Mail=_B5615A44-2992-49DE-82C6-B83654777091--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Fri, 17 Apr 2015 18:12:09 +0300
Raw View
On 17 April 2015 at 18:10, David Krauss <potswa@gmail.com> wrote:
> I think an expression-level facility would nicely complement N4461. The
> resurrected static if (or static_if) is much more sane and tractable. It
> leaves out one use-case, though: type-dependent variables and expressions.

Perhaps because std::conditional allows you to do those, if you really want.

--

---
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 http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: David Krauss <potswa@gmail.com>
Date: Fri, 17 Apr 2015 23:39:20 +0800
Raw View
--Apple-Mail=_8B91C66C-91BC-497A-A2DF-E31DB90E2131
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8


> On 2015=E2=80=9304=E2=80=9317, at 11:12 PM, Ville Voutilainen <ville.vout=
ilainen@gmail.com> wrote:
>=20
> Perhaps because std::conditional allows you to do those, if you really wa=
nt.

Only, as I mentioned, if it=E2=80=99s possible to write a generic initializ=
er. Given that overloads already solve all the problems, the point of stati=
c if or _Generic is just to avoid resorting to an overload set.

You could use std::conditional for the type-id of the declaration and _Gene=
ric for the initializer. Different solutions for different problems. (But g=
iven the initializer, auto would probably be a popular choice.)

--=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 http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--Apple-Mail=_8B91C66C-91BC-497A-A2DF-E31DB90E2131
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9304=
=E2=80=9317, at 11:12 PM, Ville Voutilainen &lt;<a href=3D"mailto:ville.vou=
tilainen@gmail.com" class=3D"">ville.voutilainen@gmail.com</a>&gt; wrote:</=
div><br class=3D"Apple-interchange-newline"><div class=3D"">Perhaps because=
 std::conditional allows you to do those, if you really want.<br class=3D""=
></div></blockquote><div><br class=3D""></div><div>Only, as I mentioned, if=
 it=E2=80=99s possible to write a generic initializer. Given that overloads=
 already solve all the problems, the point of <font face=3D"Courier" class=
=3D"">static if</font> or <font face=3D"Courier" class=3D"">_Generic</font>=
 is just to avoid resorting to an overload set.</div><div><br class=3D""></=
div><div>You could use <font face=3D"Courier" class=3D"">std::conditional</=
font> for the type-id of the declaration and&nbsp;<span style=3D"font-famil=
y: Courier;" class=3D"">_Generic</span>&nbsp;for the initializer. Different=
 solutions for different problems. (But given the initializer, <font face=
=3D"Courier" class=3D"">auto</font> would probably be a popular choice.)</d=
iv></div></body></html>

<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"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--Apple-Mail=_8B91C66C-91BC-497A-A2DF-E31DB90E2131--

.