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 <fon=
t face=3D"Courier" class=3D"">static if</font> (or <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 <span style=3D"font-family=
: Courier;" class=3D"">static if</span> 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""> ((void) _Generic( std::bool_constant< CONDITION &=
gt;{}, \</font></div><div class=3D""><font face=3D"Courier" class=3D"">&nbs=
p; std::true_type: []{ UNPAREN IF }(), \</font></div><=
div class=3D""><font face=3D"Courier" class=3D"">  =
; std::false_type: []{ UNPAREN ELSE }() ) \</font></div><div class=3D""><fo=
nt face=3D"Courier" class=3D""> ))</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""> =
; ([&]{</font></div><div class=3D""><font face=3D"Courier" class=
=3D""> static if ( std::is_same_v< decltype( =
EXPR ), TYPE > ) {</font></div><div class=3D""><font face=3D"Courier" cl=
ass=3D""> return IF;</font></div><=
div class=3D""><font face=3D"Courier" class=3D"">  =
; } static else {</font></div><div class=3D""><font face=3D"Courier" class=
=3D""> return ELSE;</font></div><d=
iv class=3D""><font face=3D"Courier" class=3D""> =
}</font></div><div class=3D""><font face=3D"Courier" class=3D""> &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 <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" 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 <<a href=3D"mailto:ville.vou=
tilainen@gmail.com" class=3D"">ville.voutilainen@gmail.com</a>> 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 <span style=3D"font-famil=
y: Courier;" class=3D"">_Generic</span> 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" 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--
.