Topic: if requires: the concepts-based if constexpr


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 25 Jun 2016 11:56:40 -0700 (PDT)
Raw View
------=_Part_233_687326043.1466881000829
Content-Type: multipart/alternative;
 boundary="----=_Part_234_30921928.1466881000829"

------=_Part_234_30921928.1466881000829
Content-Type: text/plain; charset=UTF-8

Concepts introduces the notion of the `requires` clause: a boolean
expression. C++17 will likely introduce if constexpr, which is a condition
based on a constant expression.

Since requirements are by definition constexpr, it makes sense to be able
to combine the two with:

if requires(...) {...}

Now yes, `requires` clauses are `constexpr`, so it would be possible as is
to use them with `if constexpr`:

if constexpr (requires(...) {...})

But there's no need to say the same thing multiple times. With concepts and
`if constexpr`, I can very easily see people wanting to use them in tandem,
so having shorter syntax is not unreasonable. This is similar to how
`concept` also implies `constexpr`, without us explicitly having to say it.

Consider the visual difference between:

if requires(T a) {a.SomeFunc();}

and

if constexpr(requires(T a) {a.SomeFunc();})

One useful thing here is that we often already have the equivalent of `T a`
somewhere in the program, so most uses of `if requires` would just have an
empty parameter list.

Note that `if requires` would have semantic differences from
`if(requires{...})`. The latter is a regular `if` statement that just so
happens to use a `requires` expression. The former follows the rules of a
true `if constexpr`.

This feature could also be used to give us a way of dealing with the
definition checking issue. One of the issues with definition checking is
that template implementations that are governed by a concept sometimes want
to have optional components. If a type has some function, then it will call
it, but types which don't have that function are OK as well.  Such things
are not listed in the concept's constraints because it is something which
all types can fulfill. That is, there is no actual constraint requirement;
it is a semantic constraint rather than a syntactic one.

The usual way of definition testing is to match the expressions in the
constraint with the dependent expressions used in the template. Those which
don't match the constraint requirements are illegal. This would prevent the
use of such optional features, since by definition they would not be listed
in the constraint requirements.

By wrapping such expressions in an `if requires` clause, we're effectively
saying that we are adding to the list of expressions that we permit within
the template. The reason being that the conditional makes sure that the
implementation provides an alternative if the functionality is not present.
So if you want to log certain information, and your `Log` function is
intended to accept any type, you would do this:

if requires() {Log(a);}
{
  Log(a);
}

If it turns out that someone provides some type that uses specializations
to prevent `Log` from being called on it, then the `requires` clause will
be false and the function will not be called. If you want that to be a
compile error, you can still do so:

if requires() {Log(a);}
{
  Log(a);
}
else
  static_assert(false, "Why did you do that?");

We could improve this by making it require less repetition:

if requires
{
  Log(a);
}

Since a `requires` expression normally needs a parameter list, the use of
`if requires` without such a list has special meaning. It should mean that
all of the (dependent) expressions in the `if` statement body should be
considered part of the `requires` clause. Therefore, if any of those
requirements are not met, the `requires` clause yields `false`, and the
`else` clause triggers (if any).

--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/97c876f2-bde5-4555-a18d-3bae8c4abc24%40isocpp.org.

------=_Part_234_30921928.1466881000829
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Concepts introduces the notion of the `requires` clause: a=
 boolean expression. C++17 will likely introduce if constexpr, which is a c=
ondition based on a constant expression.<br><br>Since requirements are by d=
efinition constexpr, it makes sense to be able to combine the two with:<br>=
<br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250=
); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px=
; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpret=
typrint"><span style=3D"color: #008;" class=3D"styled-by-prettify">if</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> requires</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">(...)</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">{...}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><br>No=
w yes, `requires` clauses are `constexpr`, so it would be possible as is to=
 use them with `if constexpr`:<br><br><div class=3D"prettyprint" style=3D"b=
ackground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bord=
er-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"=
prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">if</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">constexpr</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">requires</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">(...)</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{...})</span></div></code>=
</div><br>But there&#39;s no need to say the same thing multiple times. Wit=
h concepts and `if constexpr`, I can very easily see people wanting to use =
them in tandem, so having shorter syntax is not unreasonable. This is simil=
ar to how `concept` also implies `constexpr`, without us explicitly having =
to say it.<br><br>Consider the visual difference between:<br><br><div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> requires</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">T a</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</=
span><span style=3D"color: #606;" class=3D"styled-by-prettify">SomeFunc</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">();}</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></c=
ode></div><br>and<br><br><div class=3D"prettyprint" style=3D"background-col=
or: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: sol=
id; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint">=
<div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-=
by-prettify">if</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">cons=
texpr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">requires</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">T a</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">a</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">.</span><span style=3D"color: #606;" class=3D"styled-by-prettify">So=
meFunc</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();}=
)</span></div></code></div><br>One useful thing here is that we often alrea=
dy have the equivalent of `T a` somewhere in the program, so most uses of `=
if requires` would just have an empty parameter list.<br><br>Note that `if =
requires` would have semantic differences from `if(requires{...})`. The lat=
ter is a regular `if` statement that just so happens to use a `requires` ex=
pression. The former follows the rules of a true `if constexpr`.<br><br>Thi=
s feature could also be used to give us a way of dealing with the definitio=
n checking issue. One of the issues with definition checking is that templa=
te implementations that are governed by a concept sometimes want to have op=
tional components. If a type has some function, then it will call it, but t=
ypes which don&#39;t have that function are OK as well.=C2=A0 Such things a=
re not listed in the concept&#39;s constraints because it is something whic=
h all types can fulfill. That is, there is no actual constraint requirement=
; it is a semantic constraint rather than a syntactic one.<br><br>The usual=
 way of definition testing is to match the expressions in the constraint wi=
th the dependent expressions used in the template. Those which don&#39;t ma=
tch the constraint requirements are illegal. This would prevent the use of =
such optional features, since by definition they would not be listed in the=
 constraint requirements.<br><br>By wrapping such expressions in an `if req=
uires` clause, we&#39;re effectively saying that we are adding to the list =
of expressions that we permit within the template. The reason being that th=
e conditional makes sure that the implementation provides an alternative if=
 the functionality is not present. So if you want to log certain informatio=
n, and your `Log` function is intended to accept any type, you would do thi=
s:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 25=
0, 250); border-color: rgb(187, 187, 187); border-style: solid; border-widt=
h: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"s=
ubprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">if=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> requires<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">Log</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">a</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">);}</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Log</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify">a</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">}</span></div></code></div><br>If it turns ou=
t that someone provides some type that uses specializations to prevent `Log=
` from being called on it, then the `requires` clause will be false and the=
 function will not be called. If you want that to be a compile error, you c=
an still do so:<br><br><div class=3D"prettyprint" style=3D"background-color=
: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid=
; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><d=
iv class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by=
-prettify">if</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> requires</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span s=
tyle=3D"color: #606;" class=3D"styled-by-prettify">Log</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">a</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">);}</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>=C2=A0 </span><span style=3D"color: #606;" class=3D"styled-by-prett=
ify">Log</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">a</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">else</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">static_assert</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">false</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #080;" class=3D"styled-by-prettify">&quot;Wh=
y did you do that?&quot;</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">);</span></div></code></div><br>We could improve this by maki=
ng it require less repetition:<br><br><div class=3D"prettyprint" style=3D"b=
ackground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bord=
er-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"=
prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">if</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> requires<br></span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 </span><span style=3D"color: #606;" class=3D"styled-=
by-prettify">Log</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">a</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></code></div=
><br>Since a `requires` expression normally needs a parameter list, the use=
 of `if requires` without such a list has special meaning. It should mean t=
hat all of the (dependent) expressions in the `if` statement body should be=
 considered part of the `requires` clause. Therefore, if any of those requi=
rements are not met, the `requires` clause yields `false`, and the `else` c=
lause triggers (if any).<br></div>

<p></p>

-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/97c876f2-bde5-4555-a18d-3bae8c4abc24%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/97c876f2-bde5-4555-a18d-3bae8c4abc24=
%40isocpp.org</a>.<br />

------=_Part_234_30921928.1466881000829--

------=_Part_233_687326043.1466881000829--

.


Author: Zhihao Yuan <zy@miator.net>
Date: Sat, 25 Jun 2016 14:21:54 -0500
Raw View
On Sat, Jun 25, 2016 at 1:56 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> Consider the visual difference between:
>
> if requires(T a) {a.SomeFunc();}
>
> and
>
> if constexpr(requires(T a) {a.SomeFunc();})
>

  #define required(expr, ...) constexpr (requires(__VA_ARGS__) { expr; })

  if required(a.SomeFunc(), T a)
        do_something();
  if required(Log(a))
        Log(a);

  // gcc -E
  if constexpr (requires(T a) { a.SomeFunc(); })
   do_something();
  if constexpr (requires() { Log(a); })
   Log(a);

> else
>   static_assert(false, "Why did you do that?");

Not supported in C++17.  Papers fixing static_assert's
interaction with constexpr if are welcome.

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://blog.miator.net/

--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAGsORuBLuE0UbQDzmxus%2ByWve916%2BpTLqnJJSs6a3GfLQYzaUQ%40mail.gmail.com.

.


Author: Tom Honermann <tom@honermann.net>
Date: Sun, 26 Jun 2016 18:03:24 -0400
Raw View
This is a multi-part message in MIME format.
--------------040107090800060603070604
Content-Type: text/plain; charset=UTF-8; format=flowed

This idea came up previously [1], but to my knowledge has not been
discussed as thoroughly as you presented here.  The following example
was provided in that email thread:

template<InputIterator I>
I advance(I i, int n) {
   if requires(RandomAccessIterator<I>()) {
     i += n;
   } else {
     while (n > 0)
       ++i;
   }
}

The above does use a different syntax then what you proposed. Rather
than using a requires expression with the if statement, the above uses a
requires clause.  I find the above more natural, though it does open the
door to cases of 'requires requires' if one wants to add requirements
based on arbitrary expressions rather than on a constraint-expression.

I agree with your presentation of the semantic differences between 'if
requires' and 'if constexpr(requires {})'.  In particular, the former is
explicit that a constraint is being added to (a portion of) the function
definition and, in a definition checking future, it seems reasonable to
then restrict uses of expressions that would otherwise fail a constraint
check to the body of the if statement.  In the latter case, it is not
obvious to me whether such expressions could be used in the 'if
constexpr' condition (e.g., in a conjunction following the requires
expression), or would be restricted to the statement body.  I would
expect a compiler's ability to reason about the constraints to be
simpler for the former case as well.

I'm not sure about the idea to implicitly allow any expressions used in
the statement body if the 'if requires' doesn't explicitly list
constraints.  It seems like that would require speculative instantiation
which, as I understand it, would be difficult for at least some
implementors.

I do like this approach and have been intending to write a paper about
it, but time and energy...  I think a feature like this is necessary for
template definition checking to become a reality with the current
Concepts proposal.

Tom.

[1]: On the EWG reflector, email thread titled "constexpr if and concept
definition checking", 2016-02-26.

On 06/25/2016 02:56 PM, Nicol Bolas wrote:
> Concepts introduces the notion of the `requires` clause: a boolean
> expression. C++17 will likely introduce if constexpr, which is a
> condition based on a constant expression.
>
> Since requirements are by definition constexpr, it makes sense to be
> able to combine the two with:
>
> |
> ifrequires(...){...}
> |
>
> Now yes, `requires` clauses are `constexpr`, so it would be possible
> as is to use them with `if constexpr`:
>
> |
> ifconstexpr(requires(...){...})
> |
>
> But there's no need to say the same thing multiple times. With
> concepts and `if constexpr`, I can very easily see people wanting to
> use them in tandem, so having shorter syntax is not unreasonable. This
> is similar to how `concept` also implies `constexpr`, without us
> explicitly having to say it.
>
> Consider the visual difference between:
>
> |
> ifrequires(T a){a.SomeFunc();}
> |
>
> and
>
> |
> ifconstexpr(requires(T a){a.SomeFunc();})
> |
>
> One useful thing here is that we often already have the equivalent of
> `T a` somewhere in the program, so most uses of `if requires` would
> just have an empty parameter list.
>
> Note that `if requires` would have semantic differences from
> `if(requires{...})`. The latter is a regular `if` statement that just
> so happens to use a `requires` expression. The former follows the
> rules of a true `if constexpr`.
>
> This feature could also be used to give us a way of dealing with the
> definition checking issue. One of the issues with definition checking
> is that template implementations that are governed by a concept
> sometimes want to have optional components. If a type has some
> function, then it will call it, but types which don't have that
> function are OK as well.  Such things are not listed in the concept's
> constraints because it is something which all types can fulfill. That
> is, there is no actual constraint requirement; it is a semantic
> constraint rather than a syntactic one.
>
> The usual way of definition testing is to match the expressions in the
> constraint with the dependent expressions used in the template. Those
> which don't match the constraint requirements are illegal. This would
> prevent the use of such optional features, since by definition they
> would not be listed in the constraint requirements.
>
> By wrapping such expressions in an `if requires` clause, we're
> effectively saying that we are adding to the list of expressions that
> we permit within the template. The reason being that the conditional
> makes sure that the implementation provides an alternative if the
> functionality is not present. So if you want to log certain
> information, and your `Log` function is intended to accept any type,
> you would do this:
>
> |
> ifrequires(){Log(a);}
> {
> Log(a);
> }
> |
>
> If it turns out that someone provides some type that uses
> specializations to prevent `Log` from being called on it, then the
> `requires` clause will be false and the function will not be called.
> If you want that to be a compile error, you can still do so:
>
> |
> ifrequires(){Log(a);}
> {
> Log(a);
> }
> else
> static_assert(false,"Why did you do that?");
> |
>
> We could improve this by making it require less repetition:
>
> |
> ifrequires
> {
> Log(a);
> }
> |
>
> Since a `requires` expression normally needs a parameter list, the use
> of `if requires` without such a list has special meaning. It should
> mean that all of the (dependent) expressions in the `if` statement
> body should be considered part of the `requires` clause. Therefore, if
> any of those requirements are not met, the `requires` clause yields
> `false`, and the `else` clause triggers (if any).
> --
> 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
> <mailto:std-proposals+unsubscribe@isocpp.org>.
> To post to this group, send email to std-proposals@isocpp.org
> <mailto:std-proposals@isocpp.org>.
> To view this discussion on the web visit
> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/97c876f2-bde5-4555-a18d-3bae8c4abc24%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/97c876f2-bde5-4555-a18d-3bae8c4abc24%40isocpp.org?utm_medium=email&utm_source=footer>.

--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5770512C.6090401%40honermann.net.

--------------040107090800060603070604
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
    <meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
  </head>
  <body bgcolor=3D"#FFFFFF" text=3D"#000000">
    <div class=3D"moz-cite-prefix">This idea came up previously [1], but
      to my knowledge has not been discussed as thoroughly as you
      presented here.=C2=A0 The following example was provided in that emai=
l
      thread:<br>
      <br>
      template&lt;InputIterator I&gt;
      <br>
      I advance(I i, int n) {
      <br>
      =C2=A0 if requires(RandomAccessIterator&lt;I&gt;()) {
      <br>
      =C2=A0=C2=A0=C2=A0 i +=3D n;
      <br>
      =C2=A0 } else {
      <br>
      =C2=A0=C2=A0=C2=A0 while (n &gt; 0)
      <br>
      =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ++i;
      <br>
      =C2=A0 }
      <br>
      }
      <br>
      <br>
      The above does use a different syntax then what you proposed.=C2=A0
      Rather than using a requires expression with the if statement, the
      above uses a requires clause.=C2=A0 I find the above more natural,
      though it does open the door to cases of 'requires requires' if
      one wants to add requirements based on arbitrary expressions
      rather than on a constraint-expression.<br>
      <br>
      I agree with your presentation of the semantic differences between
      'if requires' and 'if constexpr(requires {})'.=C2=A0 In particular, t=
he
      former is explicit that a constraint is being added to (a portion
      of) the function definition and, in a definition checking future,
      it seems reasonable to then restrict uses of expressions that
      would otherwise fail a constraint check to the body of the if
      statement.=C2=A0 In the latter case, it is not obvious to me whether
      such expressions could be used in the 'if constexpr' condition
      (e.g., in a conjunction following the requires expression), or
      would be restricted to the statement body.=C2=A0 I would expect a
      compiler's ability to reason about the constraints to be simpler
      for the former case as well.<br>
      <br>
      I'm not sure about the idea to implicitly allow any expressions
      used in the statement body if the 'if requires' doesn't explicitly
      list constraints.=C2=A0 It seems like that would require speculative
      instantiation which, as I understand it, would be difficult for at
      least some implementors.<br>
      <br>
      I do like this approach and have been intending to write a paper
      about it, but time and energy...=C2=A0 I think a feature like this is
      necessary for template definition checking to become a reality
      with the current Concepts proposal.<br>
      <br>
      Tom.<br>
      <br>
      [1]: On the EWG reflector, email thread titled "constexpr if and
      concept definition checking", 2016-02-26.<br>
      <br>
      On 06/25/2016 02:56 PM, Nicol Bolas wrote:<br>
    </div>
    <blockquote
      cite=3D"mid:97c876f2-bde5-4555-a18d-3bae8c4abc24@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">Concepts introduces the notion of the `requires`
        clause: a boolean expression. C++17 will likely introduce if
        constexpr, which is a condition based on a constant expression.<br>
        <br>
        Since requirements are by definition constexpr, it makes sense
        to be able to combine the two with:<br>
        <br>
        <div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,
          250); border-color: rgb(187, 187, 187); border-style: solid;
          border-width: 1px; word-wrap: break-word;"><code
            class=3D"prettyprint">
            <div class=3D"subprettyprint"><span style=3D"color: #008;"
                class=3D"styled-by-prettify">if</span><span style=3D"color:
                #000;" class=3D"styled-by-prettify"> requires</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(...)</=
span><span
                style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">{...}</=
span><span
                style=3D"color: #000;" class=3D"styled-by-prettify"><br>
              </span></div>
          </code></div>
        <br>
        Now yes, `requires` clauses are `constexpr`, so it would be
        possible as is to use them with `if constexpr`:<br>
        <br>
        <div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,
          250); border-color: rgb(187, 187, 187); border-style: solid;
          border-width: 1px; word-wrap: break-word;"><code
            class=3D"prettyprint">
            <div class=3D"subprettyprint"><span style=3D"color: #008;"
                class=3D"styled-by-prettify">if</span><span style=3D"color:
                #000;" class=3D"styled-by-prettify"> </span><span
                style=3D"color: #008;" class=3D"styled-by-prettify">constex=
pr</span><span
                style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify">require=
s</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(...)</=
span><span
                style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">{...})<=
/span></div>
          </code></div>
        <br>
        But there's no need to say the same thing multiple times. With
        concepts and `if constexpr`, I can very easily see people
        wanting to use them in tandem, so having shorter syntax is not
        unreasonable. This is similar to how `concept` also implies
        `constexpr`, without us explicitly having to say it.<br>
        <br>
        Consider the visual difference between:<br>
        <br>
        <div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,
          250); border-color: rgb(187, 187, 187); border-style: solid;
          border-width: 1px; word-wrap: break-word;"><code
            class=3D"prettyprint">
            <div class=3D"subprettyprint"><span style=3D"color: #008;"
                class=3D"styled-by-prettify">if</span><span style=3D"color:
                #000;" class=3D"styled-by-prettify"> requires</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify">T a</sp=
an><span
                style=3D"color: #660;" class=3D"styled-by-prettify">)</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">{</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify">a</span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">.</span=
><span
                style=3D"color: #606;" class=3D"styled-by-prettify">SomeFun=
c</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">();}</s=
pan><span
                style=3D"color: #000;" class=3D"styled-by-prettify"><br>
              </span></div>
          </code></div>
        <br>
        and<br>
        <br>
        <div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,
          250); border-color: rgb(187, 187, 187); border-style: solid;
          border-width: 1px; word-wrap: break-word;"><code
            class=3D"prettyprint">
            <div class=3D"subprettyprint"><span style=3D"color: #008;"
                class=3D"styled-by-prettify">if</span><span style=3D"color:
                #000;" class=3D"styled-by-prettify"> </span><span
                style=3D"color: #008;" class=3D"styled-by-prettify">constex=
pr</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify">require=
s</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify">T a</sp=
an><span
                style=3D"color: #660;" class=3D"styled-by-prettify">)</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">{</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify">a</span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">.</span=
><span
                style=3D"color: #606;" class=3D"styled-by-prettify">SomeFun=
c</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">();})</=
span></div>
          </code></div>
        <br>
        One useful thing here is that we often already have the
        equivalent of `T a` somewhere in the program, so most uses of
        `if requires` would just have an empty parameter list.<br>
        <br>
        Note that `if requires` would have semantic differences from
        `if(requires{...})`. The latter is a regular `if` statement that
        just so happens to use a `requires` expression. The former
        follows the rules of a true `if constexpr`.<br>
        <br>
        This feature could also be used to give us a way of dealing with
        the definition checking issue. One of the issues with definition
        checking is that template implementations that are governed by a
        concept sometimes want to have optional components. If a type
        has some function, then it will call it, but types which don't
        have that function are OK as well.=C2=A0 Such things are not listed
        in the concept's constraints because it is something which all
        types can fulfill. That is, there is no actual constraint
        requirement; it is a semantic constraint rather than a syntactic
        one.<br>
        <br>
        The usual way of definition testing is to match the expressions
        in the constraint with the dependent expressions used in the
        template. Those which don't match the constraint requirements
        are illegal. This would prevent the use of such optional
        features, since by definition they would not be listed in the
        constraint requirements.<br>
        <br>
        By wrapping such expressions in an `if requires` clause, we're
        effectively saying that we are adding to the list of expressions
        that we permit within the template. The reason being that the
        conditional makes sure that the implementation provides an
        alternative if the functionality is not present. So if you want
        to log certain information, and your `Log` function is intended
        to accept any type, you would do this:<br>
        <br>
        <div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,
          250); border-color: rgb(187, 187, 187); border-style: solid;
          border-width: 1px; word-wrap: break-word;"><code
            class=3D"prettyprint">
            <div class=3D"subprettyprint"><span style=3D"color: #008;"
                class=3D"styled-by-prettify">if</span><span style=3D"color:
                #000;" class=3D"styled-by-prettify"> requires</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">()</spa=
n><span
                style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">{</span=
><span
                style=3D"color: #606;" class=3D"styled-by-prettify">Log</sp=
an><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify">a</span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">);}</sp=
an><span
                style=3D"color: #000;" class=3D"styled-by-prettify"><br>
              </span><span style=3D"color: #660;"
                class=3D"styled-by-prettify">{</span><span style=3D"color:
                #000;" class=3D"styled-by-prettify"><br>
                =C2=A0 </span><span style=3D"color: #606;"
                class=3D"styled-by-prettify">Log</span><span style=3D"color=
:
                #660;" class=3D"styled-by-prettify">(</span><span
                style=3D"color: #000;" class=3D"styled-by-prettify">a</span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">);</spa=
n><span
                style=3D"color: #000;" class=3D"styled-by-prettify"><br>
              </span><span style=3D"color: #660;"
                class=3D"styled-by-prettify">}</span></div>
          </code></div>
        <br>
        If it turns out that someone provides some type that uses
        specializations to prevent `Log` from being called on it, then
        the `requires` clause will be false and the function will not be
        called. If you want that to be a compile error, you can still do
        so:<br>
        <br>
        <div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,
          250); border-color: rgb(187, 187, 187); border-style: solid;
          border-width: 1px; word-wrap: break-word;"><code
            class=3D"prettyprint">
            <div class=3D"subprettyprint"><span style=3D"color: #008;"
                class=3D"styled-by-prettify">if</span><span style=3D"color:
                #000;" class=3D"styled-by-prettify"> requires</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">()</spa=
n><span
                style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">{</span=
><span
                style=3D"color: #606;" class=3D"styled-by-prettify">Log</sp=
an><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify">a</span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">);}</sp=
an><span
                style=3D"color: #000;" class=3D"styled-by-prettify"><br>
              </span><span style=3D"color: #660;"
                class=3D"styled-by-prettify">{</span><span style=3D"color:
                #000;" class=3D"styled-by-prettify"><br>
                =C2=A0 </span><span style=3D"color: #606;"
                class=3D"styled-by-prettify">Log</span><span style=3D"color=
:
                #660;" class=3D"styled-by-prettify">(</span><span
                style=3D"color: #000;" class=3D"styled-by-prettify">a</span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">);</spa=
n><span
                style=3D"color: #000;" class=3D"styled-by-prettify"><br>
              </span><span style=3D"color: #660;"
                class=3D"styled-by-prettify">}</span><span style=3D"color:
                #000;" class=3D"styled-by-prettify"><br>
              </span><span style=3D"color: #008;"
                class=3D"styled-by-prettify">else</span><span
                style=3D"color: #000;" class=3D"styled-by-prettify"><br>
                =C2=A0 </span><span style=3D"color: #008;"
                class=3D"styled-by-prettify">static_assert</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span
                style=3D"color: #008;" class=3D"styled-by-prettify">false</=
span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">,</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
                style=3D"color: #080;" class=3D"styled-by-prettify">"Why di=
d
                you do that?"</span><span style=3D"color: #660;"
                class=3D"styled-by-prettify">);</span></div>
          </code></div>
        <br>
        We could improve this by making it require less repetition:<br>
        <br>
        <div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,
          250); border-color: rgb(187, 187, 187); border-style: solid;
          border-width: 1px; word-wrap: break-word;"><code
            class=3D"prettyprint">
            <div class=3D"subprettyprint"><span style=3D"color: #008;"
                class=3D"styled-by-prettify">if</span><span style=3D"color:
                #000;" class=3D"styled-by-prettify"> requires<br>
              </span><span style=3D"color: #660;"
                class=3D"styled-by-prettify">{</span><span style=3D"color:
                #000;" class=3D"styled-by-prettify"><br>
                =C2=A0 </span><span style=3D"color: #606;"
                class=3D"styled-by-prettify">Log</span><span style=3D"color=
:
                #660;" class=3D"styled-by-prettify">(</span><span
                style=3D"color: #000;" class=3D"styled-by-prettify">a</span=
><span
                style=3D"color: #660;" class=3D"styled-by-prettify">);</spa=
n><span
                style=3D"color: #000;" class=3D"styled-by-prettify"><br>
              </span><span style=3D"color: #660;"
                class=3D"styled-by-prettify">}</span></div>
          </code></div>
        <br>
        Since a `requires` expression normally needs a parameter list,
        the use of `if requires` without such a list has special
        meaning. It should mean that all of the (dependent) expressions
        in the `if` statement body should be considered part of the
        `requires` clause. Therefore, if any of those requirements are
        not met, the `requires` clause yields `false`, and the `else`
        clause triggers (if any).<br>
      </div>
      -- <br>
      You received this message because you are subscribed to the Google
      Groups "ISO C++ Standard - Future Proposals" group.<br>
      To unsubscribe from this group and stop receiving emails from it,
      send an email to <a moz-do-not-send=3D"true"
        href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+=
unsubscribe@isocpp.org</a>.<br>
      To post to this group, send email to <a moz-do-not-send=3D"true"
        href=3D"mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</=
a>.<br>
      To view this discussion on the web visit <a
        moz-do-not-send=3D"true"
href=3D"https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/97c876=
f2-bde5-4555-a18d-3bae8c4abc24%40isocpp.org?utm_medium=3Demail&amp;utm_sour=
ce=3Dfooter"><a class=3D"moz-txt-link-freetext" href=3D"https://groups.goog=
le.com/a/isocpp.org/d/msgid/std-proposals/97c876f2-bde5-4555-a18d-3bae8c4ab=
c24%40isocpp.org">https://groups.google.com/a/isocpp.org/d/msgid/std-propos=
als/97c876f2-bde5-4555-a18d-3bae8c4abc24%40isocpp.org</a></a>.<br>
    </blockquote>
    <br>
  </body>
</html>

<p></p>

-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/5770512C.6090401%40honermann.net?utm_=
medium=3Demail&utm_source=3Dfooter">https://groups.google.com/a/isocpp.org/=
d/msgid/std-proposals/5770512C.6090401%40honermann.net</a>.<br />

--------------040107090800060603070604--

.