Topic: Allowing overloadable operators to be implemented


Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sat, 8 Feb 2014 14:07:41 -0800 (PST)
Raw View
------=_Part_457_28415547.1391897261209
Content-Type: text/plain; charset=UTF-8

It's a good question.  I too would like to know the rationale for why these
operators are not allowed in free function form:

At namespace scope:

    struct T{}; struct U{}; struct V();

    T operator=(U,V);
    T operator[](U,V);
    T operator*(U);
    T operator->(U,V);
    T operator()(U,V);

The builtin meanings already participate in overload resolution as free
functions in this form as defined in 13.6 Builtin Operators.  I don't see
any technical reason why this is ill-formed.  In fact it is nearly trivial
to add to an implementation.

Furthermore, why can't the conditional operator be overloaded?

    T operator?:(U,V,W);

The builtin operator?: too participates in overload resolution.

On Saturday, February 8, 2014 10:36:21 PM UTC+1, David Stone wrote:
>
> The following operators must be implemented as member functions:
>
> * assignment operator (`operator=`)
> * array subscript operator (`operator[]`)
> * dereference operator (unary `operator*`)
> * member access through pointer operator (`operator->`)
> * function call operator (`operator()`)
>
> There seems to be no technical reason for preventing these from being
> implemented as free functions (non-member functions).
>
> The two exceptions I can think of are the compiler-generated copy and move
> assignment operators. It seems reasonable to require them to be member
> functions, because otherwise the compiler would be unable to generate those
> when it finishes parsing the class. I am not too attached to being able to
> provide free-function definitions of `operator=` for other arguments,
> except that the restriction is artificial. We already have special cases
> for the copy and move assignment operators in the form templates never
> being considered instead of the compiler-generated version. The other
> operators are much more important to me.
>
> The use case that motivates this proposal is an integer class. I can
> define this:
>
> template<typename T>
> T * operator+(T * const pointer, my_integer const & offset) {
>     return pointer + offset.value();
> }
>
> And everything is fine. I cannot, however, define this:
>
> template<typename T>
> T & operator[](T * const pointer, my_integer const & index) {
>     return pointer[offset.value()];
> }
>
> Because `operator[]` must be a member function, and I cannot add member
> functions to a pointer. This forces users of my class to treat my class
> different from built-in types by always using `*(pointer + index)`, which
> violates C++'s design goal of not giving built-in types advantages over
> user-defined types.
>
> I also have several classes where I would implement the dereference
> operator and member access through pointer operator for some of my classes
> as free functions (following the general advice of maximizing encapsulation
> by preferring free functions over member functions / friend functions), but
> I cannot.
>
> It seems that any objections to allowing these to be non-member functions
> would apply to allowing any operator to be implementable as a non-member
> function. Consistency and allowing increased encapsulation seem to be
> strong arguments in favor of allowing.
>

--

---
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/.

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

<div dir=3D"ltr">It's a good question. &nbsp;I too would like to know the r=
ationale for why these operators are not allowed in free function form:<div=
><br></div><div>At namespace scope:</div><div><br></div><div><span style=3D=
"font-family: 'courier new', monospace;">&nbsp; &nbsp;</span><span style=3D=
"font-family: 'courier new', monospace;">&nbsp;s</span><span style=3D"font-=
family: 'courier new', monospace;">truct T{}; struct U{}; struct V();</span=
></div><div><span style=3D"font-family: 'courier new', monospace;"><br></sp=
an></div><div><span style=3D"font-family: 'courier new', monospace;">&nbsp;=
 &nbsp; T operator=3D(U,V);</span><br></div><div><font face=3D"courier new,=
 monospace">&nbsp; &nbsp; T operator[](U,V);<br>&nbsp; &nbsp; T operator*(U=
);</font></div><div><font face=3D"courier new, monospace">&nbsp; &nbsp; T o=
perator-&gt;(U,V);</font></div><div><font face=3D"courier new, monospace">&=
nbsp; &nbsp; T operator()(U,V);</font></div><div><br></div><div>The builtin=
 meanings already participate in overload resolution as free functions in t=
his form as defined in 13.6 Builtin Operators. &nbsp;I don't see any techni=
cal reason why this is ill-formed. &nbsp;In fact it is nearly trivial to ad=
d to an implementation.</div><div><br></div><div>Furthermore, why can't the=
 conditional operator be overloaded?</div><div><br></div><div><font face=3D=
"courier new, monospace">&nbsp; &nbsp; T operator?:(U,V,W);</font></div><di=
v><br></div><div>The builtin operator?: too participates in overload resolu=
tion.</div><div><br></div><div>On Saturday, February 8, 2014 10:36:21 PM UT=
C+1, David Stone wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div di=
r=3D"ltr">The following operators must be implemented as member functions:<=
br><br>* assignment operator (`operator=3D`)<br>* array subscript operator =
(`operator[]`)<br>* dereference operator (unary `operator*`)<br>* member ac=
cess through pointer operator (`operator-&gt;`)<br>* function call operator=
 (`operator()`)<br><br>There seems to be no technical reason for preventing=
 these from being implemented as free functions (non-member functions).<br>=
<br>The
 two exceptions I can think of are the compiler-generated copy and move=20
assignment operators. It seems reasonable to require them to be member=20
functions, because otherwise the compiler would be unable to generate=20
those when it finishes parsing the class. I am not too attached to being
 able to provide free-function definitions of `operator=3D` for other=20
arguments, except that the restriction is artificial. We already have=20
special cases for the copy and move assignment operators in the form=20
templates never being considered instead of the compiler-generated=20
version. The other operators are much more important to me.<br><br>The use =
case that motivates this proposal is an integer class. I can define this:<b=
r><br>template&lt;typename T&gt;<br>T * operator+(T * const pointer, my_int=
eger const &amp; offset) {<br>&nbsp; &nbsp; return pointer + offset.value()=
;<br>}<br><br>And everything is fine. I cannot, however, define this:<br><b=
r>template&lt;typename T&gt;<br>T &amp; operator[](T * const pointer, my_in=
teger const &amp; index) {<br>&nbsp; &nbsp; return pointer[offset.value()];=
<br>}<br><br>Because
 `operator[]` must be a member function, and I cannot add member=20
functions to a pointer. This forces users of my class to treat my class=20
different from built-in types by always using `*(pointer + index)`,=20
which violates C++'s design goal of not giving built-in types advantages
 over user-defined types.<br><br>I also have several classes where I=20
would implement the dereference operator and member access through=20
pointer operator for some of my classes as free functions (following the
 general advice of maximizing encapsulation by preferring free functions
 over member functions / friend functions), but I cannot.<br><br>It=20
seems that any objections to allowing these to be non-member functions=20
would apply to allowing any operator to be implementable as a non-member
 function. Consistency and allowing increased encapsulation seem to be=20
strong arguments in favor of allowing.</div></blockquote></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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 />

------=_Part_457_28415547.1391897261209--

.


Author: David Stone <deusexsophismata@gmail.com>
Date: Sat, 8 Feb 2014 14:35:52 -0800 (PST)
Raw View
------=_Part_3_19676703.1391898952256
Content-Type: text/plain; charset=UTF-8

The conditional operator is a bit trickier. I would also like to overload
that operator, but the problem is that it has short-circuit evaluation.
Unless it received special treatment, all arguments would always be
evaluated once, and the recommendation would be "never overload it", much
like operator&& and operator|| right now. My actual use case doesn't change
what the operator means, just the type. Unfortunately, we defined
std::common_type in terms of operator?:, not the other way around.
operator?: only works in the case where one of the two possible results can
be converted to the other, but in my use case, the common type of my
numeric type is a numeric type that contains the range of both values. This
has forced me to use the hideous implementation of a macro defined as

((condition) ? \
    static_cast<std::common_type_t<decltype(lhs), decltype(rhs)>>(lhs) : \
    static_cast<std::common_type_t<decltype(lhs), decltype(rhs)>>(rhs))


Where std::common_type has been specialized for my integer type to return
an integer that can hold values that either can hold.

I don't know of a good answer to this problem. It would surprise people to
write a function where the arguments are not always evaluated exactly once,
but it would also surprise people to always evaluate both possible results.

--

---
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/.

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

<div dir=3D"ltr">The conditional operator is a bit trickier. I would also l=
ike to overload that operator, but the problem is that it has short-circuit=
 evaluation. Unless it received special treatment, all arguments would alwa=
ys be evaluated once, and the recommendation would be "never overload it", =
much like operator&amp;&amp; and operator|| right now. My actual use case d=
oesn't change what the operator means, just the type. Unfortunately, we def=
ined std::common_type in terms of operator?:, not the other way around. ope=
rator?: only works in the case where one of the two possible results can be=
 converted to the other, but in my use case, the common type of my numeric =
type is a numeric type that contains the range of both values. This has for=
ced me to use the hideous implementation of a macro defined as<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-wr=
ap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint">=
<span style=3D"color: #660;" class=3D"styled-by-prettify">((</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">condition</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"col=
or: #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"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">\</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">static_cast</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">common=
_type_t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt=
;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">decltype<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">lhs</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">),</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">decltype</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">rhs</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">)&gt;&gt;(</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">lhs</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><spa=
n 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>&nbsp; &nbsp; </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">static_cast</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">common_type_t</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">decltype</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">lhs</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">),</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">decltype<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">rhs</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">)&gt;&gt;(</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">rhs</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">))</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br><br></span></div></code></div><br>Wher=
e std::common_type has been specialized for my integer type to return an in=
teger that can hold values that either can hold.<br><br>I don't know of a g=
ood answer to this problem. It would surprise people to write a function wh=
ere the arguments are not always evaluated exactly once, but it would also =
surprise people to always evaluate both possible results.<br></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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 />

------=_Part_3_19676703.1391898952256--

.


Author: morwenn29@gmail.com
Date: Sat, 8 Feb 2014 15:08:13 -0800 (PST)
Raw View
------=_Part_602_29372357.1391900893734
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Concerning the ternary operator, Stroustrup said:

"There is no fundamental reason to disallow overloading of ?:. I just=20
didn't see the need to introduce the special case of overloading a ternary=
=20
operator. Note that a function overloading expr1?expr2:expr3 would not be=
=20
able to guarantee that only one of expr2 and expr3 was executed."

I can't find where I read it, but I'm pretty sure that the rationale for=20
operator[] and all the others are that semantically speaking, they are=20
meant to access the private members of a class in order to work. Therefore,=
=20
allowing them as non-member functions would encourage using more friends or=
=20
more public class members which is somehow like saying "please, break=20
encapsulation".

Le samedi 8 f=C3=A9vrier 2014 22:36:21 UTC+1, David Stone a =C3=A9crit :
>
> The following operators must be implemented as member functions:
>
> * assignment operator (`operator=3D`)
> * array subscript operator (`operator[]`)
> * dereference operator (unary `operator*`)
> * member access through pointer operator (`operator->`)
> * function call operator (`operator()`)
>
> There seems to be no technical reason for preventing these from being=20
> implemented as free functions (non-member functions).
>
> The two exceptions I can think of are the compiler-generated copy and mov=
e=20
> assignment operators. It seems reasonable to require them to be member=20
> functions, because otherwise the compiler would be unable to generate tho=
se=20
> when it finishes parsing the class. I am not too attached to being able t=
o=20
> provide free-function definitions of `operator=3D` for other arguments,=
=20
> except that the restriction is artificial. We already have special cases=
=20
> for the copy and move assignment operators in the form templates never=20
> being considered instead of the compiler-generated version. The other=20
> operators are much more important to me.
>
> The use case that motivates this proposal is an integer class. I can=20
> define this:
>
> template<typename T>
> T * operator+(T * const pointer, my_integer const & offset) {
>     return pointer + offset.value();
> }
>
> And everything is fine. I cannot, however, define this:
>
> template<typename T>
> T & operator[](T * const pointer, my_integer const & index) {
>     return pointer[offset.value()];
> }
>
> Because `operator[]` must be a member function, and I cannot add member=
=20
> functions to a pointer. This forces users of my class to treat my class=
=20
> different from built-in types by always using `*(pointer + index)`, which=
=20
> violates C++'s design goal of not giving built-in types advantages over=
=20
> user-defined types.
>
> I also have several classes where I would implement the dereference=20
> operator and member access through pointer operator for some of my classe=
s=20
> as free functions (following the general advice of maximizing encapsulati=
on=20
> by preferring free functions over member functions / friend functions), b=
ut=20
> I cannot.
>
> It seems that any objections to allowing these to be non-member functions=
=20
> would apply to allowing any operator to be implementable as a non-member=
=20
> function. Consistency and allowing increased encapsulation seem to be=20
> strong arguments in favor of allowing.
>

--=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/.

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

<div dir=3D"ltr">Concerning the ternary operator, Stroustrup said:<br><br>"=
There is no fundamental reason to
  disallow overloading of ?:. I just
  didn't see the need to introduce the
  special case of overloading a ternary
  operator. Note that a function
  overloading expr1?expr2:expr3 would
  not be able to guarantee that only one
  of expr2 and expr3 was executed."<br><br>I can't find where I read it, bu=
t I'm pretty sure that the rationale for operator[] and all the others are =
that semantically speaking, they are meant to access the private members of=
 a class in order to work. Therefore, allowing them as non-member functions=
 would encourage using more friends or more public class members which is s=
omehow like saying "please, break encapsulation".<br><br>Le samedi 8 f=C3=
=A9vrier 2014 22:36:21 UTC+1, David Stone a =C3=A9crit&nbsp;:<blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;"><div dir=3D"ltr">The following operators mus=
t be implemented as member functions:<br><br>* assignment operator (`operat=
or=3D`)<br>* array subscript operator (`operator[]`)<br>* dereference opera=
tor (unary `operator*`)<br>* member access through pointer operator (`opera=
tor-&gt;`)<br>* function call operator (`operator()`)<br><br>There seems to=
 be no technical reason for preventing these from being implemented as free=
 functions (non-member functions).<br><br>The
 two exceptions I can think of are the compiler-generated copy and move=20
assignment operators. It seems reasonable to require them to be member=20
functions, because otherwise the compiler would be unable to generate=20
those when it finishes parsing the class. I am not too attached to being
 able to provide free-function definitions of `operator=3D` for other=20
arguments, except that the restriction is artificial. We already have=20
special cases for the copy and move assignment operators in the form=20
templates never being considered instead of the compiler-generated=20
version. The other operators are much more important to me.<br><br>The use =
case that motivates this proposal is an integer class. I can define this:<b=
r><br>template&lt;typename T&gt;<br>T * operator+(T * const pointer, my_int=
eger const &amp; offset) {<br>&nbsp; &nbsp; return pointer + offset.value()=
;<br>}<br><br>And everything is fine. I cannot, however, define this:<br><b=
r>template&lt;typename T&gt;<br>T &amp; operator[](T * const pointer, my_in=
teger const &amp; index) {<br>&nbsp; &nbsp; return pointer[offset.value()];=
<br>}<br><br>Because
 `operator[]` must be a member function, and I cannot add member=20
functions to a pointer. This forces users of my class to treat my class=20
different from built-in types by always using `*(pointer + index)`,=20
which violates C++'s design goal of not giving built-in types advantages
 over user-defined types.<br><br>I also have several classes where I=20
would implement the dereference operator and member access through=20
pointer operator for some of my classes as free functions (following the
 general advice of maximizing encapsulation by preferring free functions
 over member functions / friend functions), but I cannot.<br><br>It=20
seems that any objections to allowing these to be non-member functions=20
would apply to allowing any operator to be implementable as a non-member
 function. Consistency and allowing increased encapsulation seem to be=20
strong arguments in favor of allowing.</div></blockquote></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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 />

------=_Part_602_29372357.1391900893734--

.


Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sat, 8 Feb 2014 15:26:18 -0800 (PST)
Raw View
------=_Part_456_1220995.1391901978811
Content-Type: text/plain; charset=UTF-8

The parser sees expr1 ? expr2 : expr3.  It annotates the types and value
categories of the three subexpressions.  It then performs overload
resolution using the set of builtin candidates defined in [over.built]/24
and [over.built]/25:

     LR operator?:(bool, L, R);
     T operator?:(bool, T, T);

....in competition with any would-be defined overloaded operator?:s.  If the
builtin operator is selected it then proceeds as per Clause 5 Expressions
(short-circuit evaluation, conversions, etc).  If the would-be overloaded
operator?: is selected, it proceeds as a normal function call expression
involving three arguments.

This is exactly the same as the situation with operator&& and operator||.
 If an overloaded operator is selected, then it is a normal functon call
and you don't get the built-in short circuit.

This could be specified in the standard by changing about 3 or 4 words to
essentially no longer say "operator?: cannot be overloaded".

This could be implemented in a similar small amount of code in an
implementation, by simply adding "operator?:" to the lists as one of the
allowed overloaded operators.  The rest of the machinery works just the
same.


On Saturday, February 8, 2014 11:35:52 PM UTC+1, David Stone wrote:
>
> The conditional operator is a bit trickier. I would also like to overload
> that operator, but the problem is that it has short-circuit evaluation.
> Unless it received special treatment, all arguments would always be
> evaluated once, and the recommendation would be "never overload it", much
> like operator&& and operator|| right now. My actual use case doesn't change
> what the operator means, just the type. Unfortunately, we defined
> std::common_type in terms of operator?:, not the other way around.
> operator?: only works in the case where one of the two possible results can
> be converted to the other, but in my use case, the common type of my
> numeric type is a numeric type that contains the range of both values. This
> has forced me to use the hideous implementation of a macro defined as
>
> ((condition) ? \
>     static_cast<std::common_type_t<decltype(lhs), decltype(rhs)>>(lhs) : \
>     static_cast<std::common_type_t<decltype(lhs), decltype(rhs)>>(rhs))
>
>
> Where std::common_type has been specialized for my integer type to return
> an integer that can hold values that either can hold.
>
> I don't know of a good answer to this problem. It would surprise people to
> write a function where the arguments are not always evaluated exactly once,
> but it would also surprise people to always evaluate both possible results.
>

--

---
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/.

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

<div dir=3D"ltr">The parser sees expr1 ? expr2 : expr3. &nbsp;It annotates =
the types and value categories of the three subexpressions. &nbsp;It then p=
erforms overload resolution using the set of builtin candidates defined in =
[over.built]/24 and [over.built]/25:<div><br></div><div>&nbsp; &nbsp; &nbsp=
;LR operator?:(bool, L, R);</div><div>&nbsp; &nbsp; &nbsp;T operator?:(bool=
, T, T);<br></div><div><br></div><div>...in competition with any would-be d=
efined overloaded operator?:s. &nbsp;If the builtin operator is selected it=
 then proceeds as per Clause 5 Expressions (short-circuit evaluation, conve=
rsions, etc). &nbsp;If the would-be overloaded operator?: is selected, it p=
roceeds as a normal function call expression involving three arguments.</di=
v><div><br></div><div>This is exactly the same as the situation with operat=
or&amp;&amp; and operator||. &nbsp;If an overloaded operator is selected, t=
hen it is a normal functon call and you don't get the built-in short circui=
t.</div><div><br></div><div>This could be specified in the standard by chan=
ging about 3 or 4 words to essentially no longer say "operator?: cannot be =
overloaded".</div><div><br></div><div>This could be implemented in a simila=
r small amount of code in an implementation, by simply adding "operator?:" =
to the lists as one of the allowed overloaded operators. &nbsp;The rest of =
the machinery works just the same.</div><div><br><br>On Saturday, February =
8, 2014 11:35:52 PM UTC+1, David Stone wrote:<blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr">The conditional operator is a bit trickier.=
 I would also like to overload that operator, but the problem is that it ha=
s short-circuit evaluation. Unless it received special treatment, all argum=
ents would always be evaluated once, and the recommendation would be "never=
 overload it", much like operator&amp;&amp; and operator|| right now. My ac=
tual use case doesn't change what the operator means, just the type. Unfort=
unately, we defined std::common_type in terms of operator?:, not the other =
way around. operator?: only works in the case where one of the two possible=
 results can be converted to the other, but in my use case, the common type=
 of my numeric type is a numeric type that contains the range of both value=
s. This has forced me to use the hideous implementation of a macro defined =
as<br><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(=
187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><cod=
e><div><span style=3D"color:#660">((</span><span style=3D"color:#000">condi=
tion</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#660">?</span><span style=3D"color:#000"> </span=
><span style=3D"color:#660">\</span><span style=3D"color:#000"><br>&nbsp; &=
nbsp; </span><span style=3D"color:#008">static_cast</span><span style=3D"co=
lor:#660">&lt;</span><span style=3D"color:#000">std</span><span style=3D"co=
lor:#660">::</span><span style=3D"color:#000">common_type_t</span><span sty=
le=3D"color:#660"><wbr>&lt;</span><span style=3D"color:#008">decltype</span=
><span style=3D"color:#660">(</span><span style=3D"color:#000">lhs</span><s=
pan style=3D"color:#660">),</span><span style=3D"color:#000"> </span><span =
style=3D"color:#008">decltype</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#000">rhs</span><span style=3D"color:#660">)&gt;&gt;(</spa=
n><span style=3D"color:#000">lhs</span><span style=3D"color:#660">)</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">\</span><span style=
=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">static_=
cast</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000"=
>std</span><span style=3D"color:#660">::</span><span style=3D"color:#000">c=
ommon_type_t</span><span style=3D"color:#660"><wbr>&lt;</span><span style=
=3D"color:#008">decltype</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#000">lhs</span><span style=3D"color:#660">),</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">decltype</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#000">rhs</span><span style=
=3D"color:#660">)&gt;&gt;(</span><span style=3D"color:#000">rhs</span><span=
 style=3D"color:#660">))</span><span style=3D"color:#000"><br><br></span></=
div></code></div><br>Where std::common_type has been specialized for my int=
eger type to return an integer that can hold values that either can hold.<b=
r><br>I don't know of a good answer to this problem. It would surprise peop=
le to write a function where the arguments are not always evaluated exactly=
 once, but it would also surprise people to always evaluate both possible r=
esults.<br></div></blockquote></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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 />

------=_Part_456_1220995.1391901978811--

.


Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Sat, 8 Feb 2014 16:01:07 -0800 (PST)
Raw View
------=_Part_1932_29991100.1391904067600
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Don't forget the cast operator!

The cast operator I think would be the prime candidate (along with=20
operator=3D) as it allows you to glue together different libraries which no=
w=20
require explicit function calls. Prime examples are points, rects and (less=
=20
so nowadays) strings. With free cast operators you could define how a=20
wxPoint is to be interpreted as a glVec<2> for instance, without changing=
=20
wxWidgets or OpenGL.

Den s=C3=B6ndagen den 9:e februari 2014 kl. 00:26:18 UTC+1 skrev Andrew Tom=
azos:
>
> The parser sees expr1 ? expr2 : expr3.  It annotates the types and value=
=20
> categories of the three subexpressions.  It then performs overload=20
> resolution using the set of builtin candidates defined in [over.built]/24=
=20
> and [over.built]/25:
>
>      LR operator?:(bool, L, R);
>      T operator?:(bool, T, T);
>
> ...in competition with any would-be defined overloaded operator?:s.  If=
=20
> the builtin operator is selected it then proceeds as per Clause 5=20
> Expressions (short-circuit evaluation, conversions, etc).  If the would-b=
e=20
> overloaded operator?: is selected, it proceeds as a normal function call=
=20
> expression involving three arguments.
>
> This is exactly the same as the situation with operator&& and operator||.=
=20
>  If an overloaded operator is selected, then it is a normal functon call=
=20
> and you don't get the built-in short circuit.
>
> This could be specified in the standard by changing about 3 or 4 words to=
=20
> essentially no longer say "operator?: cannot be overloaded".
>
> This could be implemented in a similar small amount of code in an=20
> implementation, by simply adding "operator?:" to the lists as one of the=
=20
> allowed overloaded operators.  The rest of the machinery works just the=
=20
> same.
>
>
> On Saturday, February 8, 2014 11:35:52 PM UTC+1, David Stone wrote:
>>
>> The conditional operator is a bit trickier. I would also like to overloa=
d=20
>> that operator, but the problem is that it has short-circuit evaluation.=
=20
>> Unless it received special treatment, all arguments would always be=20
>> evaluated once, and the recommendation would be "never overload it", muc=
h=20
>> like operator&& and operator|| right now. My actual use case doesn't cha=
nge=20
>> what the operator means, just the type. Unfortunately, we defined=20
>> std::common_type in terms of operator?:, not the other way around.=20
>> operator?: only works in the case where one of the two possible results =
can=20
>> be converted to the other, but in my use case, the common type of my=20
>> numeric type is a numeric type that contains the range of both values. T=
his=20
>> has forced me to use the hideous implementation of a macro defined as
>>
>> ((condition) ? \
>>     static_cast<std::common_type_t<decltype(lhs), decltype(rhs)>>(lhs) :=
=20
>> \
>>     static_cast<std::common_type_t<decltype(lhs), decltype(rhs)>>(rhs))
>>
>>
>> Where std::common_type has been specialized for my integer type to retur=
n=20
>> an integer that can hold values that either can hold.
>>
>> I don't know of a good answer to this problem. It would surprise people=
=20
>> to write a function where the arguments are not always evaluated exactly=
=20
>> once, but it would also surprise people to always evaluate both possible=
=20
>> results.
>>
>

--=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/.

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

<div dir=3D"ltr">Don't forget the cast operator!<div><br></div><div>The cas=
t operator I think would be the prime candidate (along with operator=3D) as=
 it allows you to glue together different libraries which now require expli=
cit function calls. Prime examples are points, rects and (less so nowadays)=
 strings. With free cast operators you could define how a wxPoint is to be =
interpreted as a glVec&lt;2&gt; for instance, without changing wxWidgets or=
 OpenGL.<br><br>Den s=C3=B6ndagen den 9:e februari 2014 kl. 00:26:18 UTC+1 =
skrev Andrew Tomazos:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">The parser sees expr1 ? expr2 : expr3. &nbsp;It annotates the type=
s and value categories of the three subexpressions. &nbsp;It then performs =
overload resolution using the set of builtin candidates defined in [over.bu=
ilt]/24 and [over.built]/25:<div><br></div><div>&nbsp; &nbsp; &nbsp;LR oper=
ator?:(bool, L, R);</div><div>&nbsp; &nbsp; &nbsp;T operator?:(bool, T, T);=
<br></div><div><br></div><div>...in competition with any would-be defined o=
verloaded operator?:s. &nbsp;If the builtin operator is selected it then pr=
oceeds as per Clause 5 Expressions (short-circuit evaluation, conversions, =
etc). &nbsp;If the would-be overloaded operator?: is selected, it proceeds =
as a normal function call expression involving three arguments.</div><div><=
br></div><div>This is exactly the same as the situation with operator&amp;&=
amp; and operator||. &nbsp;If an overloaded operator is selected, then it i=
s a normal functon call and you don't get the built-in short circuit.</div>=
<div><br></div><div>This could be specified in the standard by changing abo=
ut 3 or 4 words to essentially no longer say "operator?: cannot be overload=
ed".</div><div><br></div><div>This could be implemented in a similar small =
amount of code in an implementation, by simply adding "operator?:" to the l=
ists as one of the allowed overloaded operators. &nbsp;The rest of the mach=
inery works just the same.</div><div><br><br>On Saturday, February 8, 2014 =
11:35:52 PM UTC+1, David Stone wrote:<blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr">The conditional operator is a bit trickier. I would also=
 like to overload that operator, but the problem is that it has short-circu=
it evaluation. Unless it received special treatment, all arguments would al=
ways be evaluated once, and the recommendation would be "never overload it"=
, much like operator&amp;&amp; and operator|| right now. My actual use case=
 doesn't change what the operator means, just the type. Unfortunately, we d=
efined std::common_type in terms of operator?:, not the other way around. o=
perator?: only works in the case where one of the two possible results can =
be converted to the other, but in my use case, the common type of my numeri=
c type is a numeric type that contains the range of both values. This has f=
orced me to use the hideous implementation of a macro defined as<br><br><di=
v 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><div><span =
style=3D"color:#660">((</span><span style=3D"color:#000">condition</span><s=
pan style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">?</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">\</span><span style=3D"color:#000"><br>&nbsp; &nbsp; </span=
><span style=3D"color:#008">static_cast</span><span style=3D"color:#660">&l=
t;</span><span style=3D"color:#000">std</span><span style=3D"color:#660">::=
</span><span style=3D"color:#000">common_type_t</span><span style=3D"color:=
#660"><wbr>&lt;</span><span style=3D"color:#008">decltype</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">lhs</span><span style=3D=
"color:#660">),</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#008">decltype</span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#000">rhs</span><span style=3D"color:#660">)&gt;&gt;(</span><span styl=
e=3D"color:#000">lhs</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">\</span><span style=3D"color:=
#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">static_cast</span=
><span style=3D"color:#660">&lt;</span><span style=3D"color:#000">std</span=
><span style=3D"color:#660">::</span><span style=3D"color:#000">common_type=
_t</span><span style=3D"color:#660"><wbr>&lt;</span><span style=3D"color:#0=
08">decltype</span><span style=3D"color:#660">(</span><span style=3D"color:=
#000">lhs</span><span style=3D"color:#660">),</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#008">decltype</span><span style=3D"color:=
#660">(</span><span style=3D"color:#000">rhs</span><span style=3D"color:#66=
0">)&gt;&gt;(</span><span style=3D"color:#000">rhs</span><span style=3D"col=
or:#660">))</span><span style=3D"color:#000"><br><br></span></div></code></=
div><br>Where std::common_type has been specialized for my integer type to =
return an integer that can hold values that either can hold.<br><br>I don't=
 know of a good answer to this problem. It would surprise people to write a=
 function where the arguments are not always evaluated exactly once, but it=
 would also surprise people to always evaluate both possible results.<br></=
div></blockquote></div></div></blockquote></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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 />

------=_Part_1932_29991100.1391904067600--

.


Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Sat, 8 Feb 2014 16:18:26 -0800 (PST)
Raw View
------=_Part_1940_27737498.1391905106104
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

You mean free namespace-scope conversion functions?

Like:

    struct T{}; struct U{};

    operator T(U) {}

    void f(T) {}

    int main()
    {
        U u;
        f(u);  // calls f(operator T(u))
    }


On Sunday, February 9, 2014 1:01:07 AM UTC+1, Bengt Gustafsson wrote:
>
> Don't forget the cast operator!
>
> The cast operator I think would be the prime candidate (along with=20
> operator=3D) as it allows you to glue together different libraries which =
now=20
> require explicit function calls. Prime examples are points, rects and (le=
ss=20
> so nowadays) strings. With free cast operators you could define how a=20
> wxPoint is to be interpreted as a glVec<2> for instance, without changing=
=20
> wxWidgets or OpenGL.
>
> Den s=C3=B6ndagen den 9:e februari 2014 kl. 00:26:18 UTC+1 skrev Andrew T=
omazos:
>>
>> The parser sees expr1 ? expr2 : expr3.  It annotates the types and value=
=20
>> categories of the three subexpressions.  It then performs overload=20
>> resolution using the set of builtin candidates defined in [over.built]/2=
4=20
>> and [over.built]/25:
>>
>>      LR operator?:(bool, L, R);
>>      T operator?:(bool, T, T);
>>
>> ...in competition with any would-be defined overloaded operator?:s.  If=
=20
>> the builtin operator is selected it then proceeds as per Clause 5=20
>> Expressions (short-circuit evaluation, conversions, etc).  If the would-=
be=20
>> overloaded operator?: is selected, it proceeds as a normal function call=
=20
>> expression involving three arguments.
>>
>> This is exactly the same as the situation with operator&& and operator||=
..=20
>>  If an overloaded operator is selected, then it is a normal functon call=
=20
>> and you don't get the built-in short circuit.
>>
>> This could be specified in the standard by changing about 3 or 4 words t=
o=20
>> essentially no longer say "operator?: cannot be overloaded".
>>
>> This could be implemented in a similar small amount of code in an=20
>> implementation, by simply adding "operator?:" to the lists as one of the=
=20
>> allowed overloaded operators.  The rest of the machinery works just the=
=20
>> same.
>>
>>
>> On Saturday, February 8, 2014 11:35:52 PM UTC+1, David Stone wrote:
>>>
>>> The conditional operator is a bit trickier. I would also like to=20
>>> overload that operator, but the problem is that it has short-circuit=20
>>> evaluation. Unless it received special treatment, all arguments would=
=20
>>> always be evaluated once, and the recommendation would be "never overlo=
ad=20
>>> it", much like operator&& and operator|| right now. My actual use case=
=20
>>> doesn't change what the operator means, just the type. Unfortunately, w=
e=20
>>> defined std::common_type in terms of operator?:, not the other way arou=
nd.=20
>>> operator?: only works in the case where one of the two possible results=
 can=20
>>> be converted to the other, but in my use case, the common type of my=20
>>> numeric type is a numeric type that contains the range of both values. =
This=20
>>> has forced me to use the hideous implementation of a macro defined as
>>>
>>> ((condition) ? \
>>>     static_cast<std::common_type_t<decltype(lhs), decltype(rhs)>>(lhs) =
:=20
>>> \
>>>     static_cast<std::common_type_t<decltype(lhs), decltype(rhs)>>(rhs))
>>>
>>>
>>> Where std::common_type has been specialized for my integer type to=20
>>> return an integer that can hold values that either can hold.
>>>
>>> I don't know of a good answer to this problem. It would surprise people=
=20
>>> to write a function where the arguments are not always evaluated exactl=
y=20
>>> once, but it would also surprise people to always evaluate both possibl=
e=20
>>> results.
>>>
>>

--=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/.

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

<div dir=3D"ltr">You mean free namespace-scope conversion functions?<br><br=
>Like:<div><br></div><div><font face=3D"courier new, monospace">&nbsp; &nbs=
p; struct T{}; struct U{};</font></div><div><font face=3D"courier new, mono=
space"><br></font></div><div><font face=3D"courier new, monospace">&nbsp; &=
nbsp; operator T(U) {}<br><br>&nbsp; &nbsp; void f(T) {}</font></div><div><=
font face=3D"courier new, monospace"><br></font></div><div><font face=3D"co=
urier new, monospace">&nbsp; &nbsp; int main()</font></div><div><font face=
=3D"courier new, monospace">&nbsp; &nbsp; {</font></div><div><font face=3D"=
courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; U u;</font></div><div><=
font face=3D"courier new, monospace">&nbsp; &nbsp; &nbsp; &nbsp; f(u); &nbs=
p;// calls f(operator T(u))</font></div><div><font face=3D"courier new, mon=
ospace">&nbsp; &nbsp; }<br></font></div><div><br></div><div><br></div><div>=
On Sunday, February 9, 2014 1:01:07 AM UTC+1, Bengt Gustafsson wrote:<block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Don't forget the ca=
st operator!<div><br></div><div>The cast operator I think would be the prim=
e candidate (along with operator=3D) as it allows you to glue together diff=
erent libraries which now require explicit function calls. Prime examples a=
re points, rects and (less so nowadays) strings. With free cast operators y=
ou could define how a wxPoint is to be interpreted as a glVec&lt;2&gt; for =
instance, without changing wxWidgets or OpenGL.<br><br>Den s=C3=B6ndagen de=
n 9:e februari 2014 kl. 00:26:18 UTC+1 skrev Andrew Tomazos:<blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
 solid;padding-left:1ex"><div dir=3D"ltr">The parser sees expr1 ? expr2 : e=
xpr3. &nbsp;It annotates the types and value categories of the three subexp=
ressions. &nbsp;It then performs overload resolution using the set of built=
in candidates defined in [over.built]/24 and [over.built]/25:<div><br></div=
><div>&nbsp; &nbsp; &nbsp;LR operator?:(bool, L, R);</div><div>&nbsp; &nbsp=
; &nbsp;T operator?:(bool, T, T);<br></div><div><br></div><div>...in compet=
ition with any would-be defined overloaded operator?:s. &nbsp;If the builti=
n operator is selected it then proceeds as per Clause 5 Expressions (short-=
circuit evaluation, conversions, etc). &nbsp;If the would-be overloaded ope=
rator?: is selected, it proceeds as a normal function call expression invol=
ving three arguments.</div><div><br></div><div>This is exactly the same as =
the situation with operator&amp;&amp; and operator||. &nbsp;If an overloade=
d operator is selected, then it is a normal functon call and you don't get =
the built-in short circuit.</div><div><br></div><div>This could be specifie=
d in the standard by changing about 3 or 4 words to essentially no longer s=
ay "operator?: cannot be overloaded".</div><div><br></div><div>This could b=
e implemented in a similar small amount of code in an implementation, by si=
mply adding "operator?:" to the lists as one of the allowed overloaded oper=
ators. &nbsp;The rest of the machinery works just the same.</div><div><br><=
br>On Saturday, February 8, 2014 11:35:52 PM UTC+1, David Stone wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">The conditional operato=
r is a bit trickier. I would also like to overload that operator, but the p=
roblem is that it has short-circuit evaluation. Unless it received special =
treatment, all arguments would always be evaluated once, and the recommenda=
tion would be "never overload it", much like operator&amp;&amp; and operato=
r|| right now. My actual use case doesn't change what the operator means, j=
ust the type. Unfortunately, we defined std::common_type in terms of operat=
or?:, not the other way around. operator?: only works in the case where one=
 of the two possible results can be converted to the other, but in my use c=
ase, the common type of my numeric type is a numeric type that contains the=
 range of both values. This has forced me to use the hideous implementation=
 of a macro defined as<br><br><div style=3D"background-color:rgb(250,250,25=
0);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-w=
rap:break-word"><code><div><span style=3D"color:#660">((</span><span style=
=3D"color:#000">condition</span><span style=3D"color:#660">)</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">?</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">\</span><span style=3D"c=
olor:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">static_cast<=
/span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000">std<=
/span><span style=3D"color:#660">::</span><span style=3D"color:#000">common=
_type_t</span><span style=3D"color:#660"><wbr>&lt;</span><span style=3D"col=
or:#008">decltype</span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#000">lhs</span><span style=3D"color:#660">),</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#008">decltype</span><span style=3D"c=
olor:#660">(</span><span style=3D"color:#000">rhs</span><span style=3D"colo=
r:#660">)&gt;&gt;(</span><span style=3D"color:#000">lhs</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">:</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">\</span><span style=3D"color:#000"><br>&nbsp; &nbsp; </span><span sty=
le=3D"color:#008">static_cast</span><span style=3D"color:#660">&lt;</span><=
span style=3D"color:#000">std</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#000">common_type_t</span><span style=3D"color:#660"><wbr=
>&lt;</span><span style=3D"color:#008">decltype</span><span style=3D"color:=
#660">(</span><span style=3D"color:#000">lhs</span><span style=3D"color:#66=
0">),</span><span style=3D"color:#000"> </span><span style=3D"color:#008">d=
ecltype</span><span style=3D"color:#660">(</span><span style=3D"color:#000"=
>rhs</span><span style=3D"color:#660">)&gt;&gt;(</span><span style=3D"color=
:#000">rhs</span><span style=3D"color:#660">))</span><span style=3D"color:#=
000"><br><br></span></div></code></div><br>Where std::common_type has been =
specialized for my integer type to return an integer that can hold values t=
hat either can hold.<br><br>I don't know of a good answer to this problem. =
It would surprise people to write a function where the arguments are not al=
ways evaluated exactly once, but it would also surprise people to always ev=
aluate both possible results.<br></div></blockquote></div></div></blockquot=
e></div></div></blockquote></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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 />

------=_Part_1940_27737498.1391905106104--

.


Author: David Stone <deusexsophismata@gmail.com>
Date: Sun, 9 Feb 2014 07:13:42 -0800 (PST)
Raw View
------=_Part_17_22375024.1391958822050
Content-Type: text/plain; charset=UTF-8

I would be afraid of allowing implicit conversions defined outside of a
class. Explicit conversions are fine, but allowing an implicit conversion
to be defined anywhere in the program seems likely to cause unexpected
behavior.

--

---
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/.

------=_Part_17_22375024.1391958822050
Content-Type: text/html; charset=UTF-8

<div dir="ltr">I would be afraid of allowing implicit conversions defined outside of a class. Explicit conversions are fine, but allowing an implicit conversion to be defined anywhere in the program seems likely to cause unexpected behavior.<br></div>

<p></p>

-- <br />
&nbsp;<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 email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />

------=_Part_17_22375024.1391958822050--

.


Author: David Krauss <potswa@gmail.com>
Date: Mon, 10 Feb 2014 00:10:15 +0800
Raw View
On Feb 9, 2014, at 11:13 PM, David Stone <deusexsophismata@gmail.com> wrote=
:

> I would be afraid of allowing implicit conversions defined outside of a c=
lass. Explicit conversions are fine

Old-fashioned free functions pretty well express explicit conversion. Perfe=
ct emulation comes down to allowing a function name to overload a class nam=
e. I wouldn't go there.

> , but allowing an implicit conversion to be defined anywhere in the progr=
am seems likely to cause unexpected behavior.

There might be something to be said for letting the user opt-in to "interfa=
ce glue" between modules. (Not necessarily referring to capital-M Modules, =
but just namespace-encapsulated class libraries.) C++ lacks a good way of d=
efining glue. We might not need the intrusiveness of extension methods to s=
olve this.

However, the focus of this thread seems to be elsewhere.

--=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/.

.


Author: myriachan@gmail.com
Date: Fri, 21 Feb 2014 21:21:28 -0800 (PST)
Raw View
------=_Part_782_18432393.1393046488467
Content-Type: text/plain; charset=UTF-8

It'd be hacky as all hell, but there is a way that overloading ?: could
work without losing short-circuiting or breaking the language *too* much.
I don't really know why you'd want to overload ?: in the first place, but
this could work:

const ParentOfLeftAndRight &operator ?:(
    const Conditional &conditional,
    std::function<const Left &()> getLeft,
    std::function<const Right &>() getRight)
{
  return conditional.Evaluate() ? getLeft() : getRight();
}

In other words, have the compiler generate lambdas for the expressions on
the left and right sides of the colon, and try to find an operator ?:
function that has an overload that will take that argument trio.

Melissa

On Saturday, February 8, 2014 3:26:18 PM UTC-8, Andrew Tomazos wrote:
>
> The parser sees expr1 ? expr2 : expr3.  It annotates the types and value
> categories of the three subexpressions.  It then performs overload
> resolution using the set of builtin candidates defined in [over.built]/24
> and [over.built]/25:
>
>      LR operator?:(bool, L, R);
>      T operator?:(bool, T, T);
>
> ...in competition with any would-be defined overloaded operator?:s.  If
> the builtin operator is selected it then proceeds as per Clause 5
> Expressions (short-circuit evaluation, conversions, etc).  If the would-be
> overloaded operator?: is selected, it proceeds as a normal function call
> expression involving three arguments.
>
> This is exactly the same as the situation with operator&& and operator||.
>  If an overloaded operator is selected, then it is a normal functon call
> and you don't get the built-in short circuit.
>
> This could be specified in the standard by changing about 3 or 4 words to
> essentially no longer say "operator?: cannot be overloaded".
>
> This could be implemented in a similar small amount of code in an
> implementation, by simply adding "operator?:" to the lists as one of the
> allowed overloaded operators.  The rest of the machinery works just the
> same.
>
>
> On Saturday, February 8, 2014 11:35:52 PM UTC+1, David Stone wrote:
>>
>> The conditional operator is a bit trickier. I would also like to overload
>> that operator, but the problem is that it has short-circuit evaluation.
>> Unless it received special treatment, all arguments would always be
>> evaluated once, and the recommendation would be "never overload it", much
>> like operator&& and operator|| right now. My actual use case doesn't change
>> what the operator means, just the type. Unfortunately, we defined
>> std::common_type in terms of operator?:, not the other way around.
>> operator?: only works in the case where one of the two possible results can
>> be converted to the other, but in my use case, the common type of my
>> numeric type is a numeric type that contains the range of both values. This
>> has forced me to use the hideous implementation of a macro defined as
>>
>> ((condition) ? \
>>     static_cast<std::common_type_t<decltype(lhs), decltype(rhs)>>(lhs) :
>> \
>>     static_cast<std::common_type_t<decltype(lhs), decltype(rhs)>>(rhs))
>>
>>
>> Where std::common_type has been specialized for my integer type to return
>> an integer that can hold values that either can hold.
>>
>> I don't know of a good answer to this problem. It would surprise people
>> to write a function where the arguments are not always evaluated exactly
>> once, but it would also surprise people to always evaluate both possible
>> results.
>>
>

--

---
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/.

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

<div dir=3D"ltr">It'd be hacky as all hell, but there is a way that overloa=
ding ?: could work without losing short-circuiting or breaking the language=
 <i>too</i> much.&nbsp; I don't really know why you'd want to overload ?: i=
n the first place, but this could work:<br><br>const ParentOfLeftAndRight &=
amp;operator ?:(<br>&nbsp;&nbsp;&nbsp; const Conditional &amp;conditional,<=
br>&nbsp;&nbsp;&nbsp; std::function&lt;const Left &amp;()&gt; getLeft,<br>&=
nbsp;&nbsp;&nbsp; std::function&lt;const Right &amp;&gt;() getRight)<br>{<b=
r>&nbsp; return conditional.Evaluate() ? getLeft() : getRight();<br>}<br><b=
r>In other words, have the compiler generate lambdas for the expressions on=
 the left and right sides of the colon, and try to find an operator ?: func=
tion that has an overload that will take that argument trio.<br><br>Melissa=
<br><br>On Saturday, February 8, 2014 3:26:18 PM UTC-8, Andrew Tomazos wrot=
e:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">The parser =
sees expr1 ? expr2 : expr3. &nbsp;It annotates the types and value categori=
es of the three subexpressions. &nbsp;It then performs overload resolution =
using the set of builtin candidates defined in [over.built]/24 and [over.bu=
ilt]/25:<div><br></div><div>&nbsp; &nbsp; &nbsp;LR operator?:(bool, L, R);<=
/div><div>&nbsp; &nbsp; &nbsp;T operator?:(bool, T, T);<br></div><div><br><=
/div><div>...in competition with any would-be defined overloaded operator?:=
s. &nbsp;If the builtin operator is selected it then proceeds as per Clause=
 5 Expressions (short-circuit evaluation, conversions, etc). &nbsp;If the w=
ould-be overloaded operator?: is selected, it proceeds as a normal function=
 call expression involving three arguments.</div><div><br></div><div>This i=
s exactly the same as the situation with operator&amp;&amp; and operator||.=
 &nbsp;If an overloaded operator is selected, then it is a normal functon c=
all and you don't get the built-in short circuit.</div><div><br></div><div>=
This could be specified in the standard by changing about 3 or 4 words to e=
ssentially no longer say "operator?: cannot be overloaded".</div><div><br><=
/div><div>This could be implemented in a similar small amount of code in an=
 implementation, by simply adding "operator?:" to the lists as one of the a=
llowed overloaded operators. &nbsp;The rest of the machinery works just the=
 same.</div><div><br><br>On Saturday, February 8, 2014 11:35:52 PM UTC+1, D=
avid Stone wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin=
-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">T=
he conditional operator is a bit trickier. I would also like to overload th=
at operator, but the problem is that it has short-circuit evaluation. Unles=
s it received special treatment, all arguments would always be evaluated on=
ce, and the recommendation would be "never overload it", much like operator=
&amp;&amp; and operator|| right now. My actual use case doesn't change what=
 the operator means, just the type. Unfortunately, we defined std::common_t=
ype in terms of operator?:, not the other way around. operator?: only works=
 in the case where one of the two possible results can be converted to the =
other, but in my use case, the common type of my numeric type is a numeric =
type that contains the range of both values. This has forced me to use the =
hideous implementation of a macro defined as<br><br><div style=3D"backgroun=
d-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;b=
order-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#660"=
>((</span><span style=3D"color:#000">condition</span><span style=3D"color:#=
660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
?</span><span style=3D"color:#000"> </span><span style=3D"color:#660">\</sp=
an><span style=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color=
:#008">static_cast</span><span style=3D"color:#660">&lt;</span><span style=
=3D"color:#000">std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#000">common_type_t</span><span style=3D"color:#660"><wbr>&lt;</s=
pan><span style=3D"color:#008">decltype</span><span style=3D"color:#660">(<=
/span><span style=3D"color:#000">lhs</span><span style=3D"color:#660">),</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#008">decltype<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#000">rhs</sp=
an><span style=3D"color:#660">)&gt;&gt;(</span><span style=3D"color:#000">l=
hs</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">:</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">\</span><span style=3D"color:#000"><br>&nbsp; &nb=
sp; </span><span style=3D"color:#008">static_cast</span><span style=3D"colo=
r:#660">&lt;</span><span style=3D"color:#000">std</span><span style=3D"colo=
r:#660">::</span><span style=3D"color:#000">common_type_t</span><span style=
=3D"color:#660"><wbr>&lt;</span><span style=3D"color:#008">decltype</span><=
span style=3D"color:#660">(</span><span style=3D"color:#000">lhs</span><spa=
n style=3D"color:#660">),</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#008">decltype</span><span style=3D"color:#660">(</span><span =
style=3D"color:#000">rhs</span><span style=3D"color:#660">)&gt;&gt;(</span>=
<span style=3D"color:#000">rhs</span><span style=3D"color:#660">))</span><s=
pan style=3D"color:#000"><br><br></span></div></code></div><br>Where std::c=
ommon_type has been specialized for my integer type to return an integer th=
at can hold values that either can hold.<br><br>I don't know of a good answ=
er to this problem. It would surprise people to write a function where the =
arguments are not always evaluated exactly once, but it would also surprise=
 people to always evaluate both possible results.<br></div></blockquote></d=
iv></div></blockquote></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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 />

------=_Part_782_18432393.1393046488467--

.


Author: Adam Nevraumont <afn@theorem.ca>
Date: Mon, 24 Feb 2014 12:53:14 -0800 (PST)
Raw View
------=_Part_274_27604981.1393275194511
Content-Type: text/plain; charset=UTF-8



On Saturday, February 22, 2014 12:21:28 AM UTC-5, myri...@gmail.com wrote:
>
> It'd be hacky as all hell, but there is a way that overloading ?: could
> work without losing short-circuiting or breaking the language *too*much.  I don't really know why you'd want to overload ?: in the first
> place, but this could work:
>
> const ParentOfLeftAndRight &operator ?:(
>     const Conditional &conditional,
>     std::function<const Left &()> getLeft,
>     std::function<const Right &>() getRight)
> {
>   return conditional.Evaluate() ? getLeft() : getRight();
> }
>
> In other words, have the compiler generate lambdas for the expressions on
> the left and right sides of the colon, and try to find an operator ?:
> function that has an overload that will take that argument trio.
>
 Rather,
template<typename LeftExpr, typename RightExpr>
std::common_type_t< std::result_of_t<LeftExpr()>,
std::result_of_t<RightExpr()> > operator?:(
   Conditional const& condition,
   LeftExpr&& lhs,
   RightExpr && rhs
)
{
  if (condition)
    return std::forward<LeftExpr>(lhs)();
  else
    return std::forward<RightExpr>(rhs)();
}
where
cond?lhs:rhs;
is transformed into
operator?:( cond, [&]{return lhs;}, [&]{return rhs;} )
with maybe some verbage to make sure perfect forwarding occurs.

You could naturally do the same with && and ||.  Some way (maybe something
as hacky as the int argument to ++) to distinguish between the
short-circuit and "traditional" overloads of && and ||.

Short-circuit overloads could be preferred, or it could be ambiguous if
both exist and are otherwise equally good.

Adding a non-short-circuit ?: seems like a bad idea, for the same reason
why nobody wants to override && and ||.  But if we first added
short-circuit && and ||, we can add short-circuit ?: and skip the
non-short-circuit version...




--

---
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/.

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

<div dir=3D"ltr"><br><br>On Saturday, February 22, 2014 12:21:28 AM UTC-5, =
myri...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr">It'd be hacky as all hell, but there is a way that overloading ?=
: could work without losing short-circuiting or breaking the language <i>to=
o</i> much.&nbsp; I don't really know why you'd want to overload ?: in the =
first place, but this could work:<br><br>const ParentOfLeftAndRight &amp;op=
erator ?:(<br>&nbsp;&nbsp;&nbsp; const Conditional &amp;conditional,<br>&nb=
sp;&nbsp;&nbsp; std::function&lt;const Left &amp;()&gt; getLeft,<br>&nbsp;&=
nbsp;&nbsp; std::function&lt;const Right &amp;&gt;() getRight)<br>{<br>&nbs=
p; return conditional.Evaluate() ? getLeft() : getRight();<br>}<br><br>In o=
ther words, have the compiler generate lambdas for the expressions on the l=
eft and right sides of the colon, and try to find an operator ?: function t=
hat has an overload that will take that argument trio.<br></div></blockquot=
e><div>&nbsp;Rather,<br>template&lt;typename LeftExpr, typename RightExpr&g=
t;<br>std::common_type_t&lt; std::result_of_t&lt;LeftExpr()&gt;, std::resul=
t_of_t&lt;RightExpr()&gt; &gt; operator?:(<br>&nbsp;&nbsp; Conditional cons=
t&amp; condition,<br>&nbsp;&nbsp; LeftExpr&amp;&amp; lhs,<br>&nbsp;&nbsp; R=
ightExpr &amp;&amp; rhs<br>)<br>{<br>&nbsp; if (condition)<br>&nbsp;&nbsp;&=
nbsp; return std::forward&lt;LeftExpr&gt;(lhs)();<br>&nbsp; else<br>&nbsp;&=
nbsp;&nbsp; return std::forward&lt;RightExpr&gt;(rhs)();<br>}<br>where<br>c=
ond?lhs:rhs;<br>is transformed into<br>operator?:( cond, [&amp;]{return lhs=
;}, [&amp;]{return rhs;} )<br>with maybe some verbage to make sure perfect =
forwarding occurs.<br><br>You could naturally do the same with &amp;&amp; a=
nd ||.&nbsp; Some way (maybe something as hacky as the int argument to ++) =
to distinguish between the short-circuit and "traditional" overloads of &am=
p;&amp; and ||.<br><br>Short-circuit overloads could be preferred, or it co=
uld be ambiguous if both exist and are otherwise equally good.<br><br>Addin=
g a non-short-circuit ?: seems like a bad idea, for the same reason why nob=
ody wants to override &amp;&amp; and ||.&nbsp; But if we first added short-=
circuit &amp;&amp; and ||, we can add short-circuit ?: and skip the non-sho=
rt-circuit version...<br><br><br>&nbsp;&nbsp; <br></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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 />

------=_Part_274_27604981.1393275194511--

.


Author: Andrew Tomazos <andrewtomazos@gmail.com>
Date: Wed, 26 Feb 2014 11:48:31 -0800 (PST)
Raw View
------=_Part_6609_23797656.1393444111737
Content-Type: text/plain; charset=UTF-8

On Saturday, February 22, 2014 6:21:28 AM UTC+1, myri...@gmail.com wrote:
>
> I don't really know why you'd want to overload ?: in the first place
>

Consider a linear algebra library like:

    matrix<bool> B = ...;
    matrix<float> X = ...;
    matrix<float> Y = ...;

    matrix<float> Z = (B ? X : Y);

The overloaded ?: applies the ternary operator element-wise.

Granted you could just use a normal named function, but the same argument
can be made against any operator overload.

--

---
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/.

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

<div dir=3D"ltr">On Saturday, February 22, 2014 6:21:28 AM UTC+1, myri...@g=
mail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
">I don't really know why you'd want to overload ?: in the first place</div=
></blockquote><div><br></div><div>Consider a linear algebra library like:<b=
r></div><div><br></div><div>&nbsp; &nbsp; matrix&lt;bool&gt; B =3D ...;</di=
v><div>&nbsp; &nbsp; matrix&lt;float&gt; X =3D ...;</div><div>&nbsp; &nbsp;=
 matrix&lt;float&gt; Y =3D ...;</div><div><br></div><div>&nbsp; &nbsp; matr=
ix&lt;float&gt; Z =3D (B ? X : Y);</div><div><br></div><div>The overloaded =
?: applies the ternary operator element-wise.</div><div><br></div><div>Gran=
ted you could just use a normal named function, but the same argument can b=
e made against any operator overload.</div><div><br></div></div>

<p></p>

-- <br />
&nbsp;<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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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 />

------=_Part_6609_23797656.1393444111737--

.


Author: David Krauss <potswa@gmail.com>
Date: Fri, 28 Feb 2014 10:36:13 +0800
Raw View
--Apple-Mail=_5D962BEE-0FAC-4F50-9C55-B2AC9F6B79CD
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1


On Feb 25, 2014, at 5:28 PM, Nicola Gigante <nicola.gigante@gmail.com> wrot=
e:

> Of course, lazy function parameters have a _lot_ of other applications, a=
nd such a feature would merit a separate discussion.

I've had success with this convenience class as a parameter type. Of course=
 implicit conversion has gotchas, and it's not the first solution I reach f=
or, but it's caused few headaches when I've used it.

template< typename bound >
struct implicit_thunk {
 bound f;
 operator typename std::result_of< bound() >::type ()
            { return f(); }
};

template< typename bound >
implicit_thunk< typename std::decay< bound >::type >
make_implicit_thunk( bound && f )
 { return { std::forward< bound >( f ) }; }


On Feb 27, 2014, at 3:48 AM, Andrew Tomazos <andrewtomazos@gmail.com> wrote=
:

> On Saturday, February 22, 2014 6:21:28 AM UTC+1, myri...@gmail.com wrote:
> I don't really know why you'd want to overload ?: in the first place
>=20
> Consider a linear algebra library like:
>=20
>     matrix<bool> B =3D ...;
>     matrix<float> X =3D ...;
>     matrix<float> Y =3D ...;
>=20
>     matrix<float> Z =3D (B ? X : Y);
>=20
> The overloaded ?: applies the ternary operator element-wise.

This simple use-case demands implementation by cmove instructions for good =
performance, but more sophisticated use cases would require lazy evaluation=
.. Hmm, I think the required lazy semantics could be accomplished by express=
ion templates. So this could work.

> Granted you could just use a normal named function, but the same argument=
 can be made against any operator overload.

Well, ?: does give the appearance of short-circuit behavior, but in a math =
library, subexpressions usually don't have side effects anyway. Personally =
I don't think the advantage outweighs the cost. There are so many other fun=
ctions that can't be operators, and selection such an uncommon operation, t=
hat it wouldn't change the look-and-feel of much linear algebra code.

--=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=_5D962BEE-0FAC-4F50-9C55-B2AC9F6B79CD
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dwindows-1252"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-=
mode: space; -webkit-line-break: after-white-space;"><div><br></div><div>On=
 Feb 25, 2014, at 5:28 PM, Nicola Gigante &lt;<a href=3D"mailto:nicola.giga=
nte@gmail.com">nicola.gigante@gmail.com</a>&gt; wrote:</div><br class=3D"Ap=
ple-interchange-newline"><blockquote type=3D"cite">Of course, lazy function=
 parameters have a _lot_ of other applications, and such a feature would me=
rit a separate discussion.<br></blockquote><div><br></div><div>I&rsquo;ve h=
ad success with this convenience class as a parameter type. Of course impli=
cit conversion has gotchas, and it&rsquo;s not the first solution I reach f=
or, but it&rsquo;s caused few headaches when I&rsquo;ve used it.</div><div>=
<br></div><div><div><font face=3D"Courier">template&lt; typename bound &gt;=
</font></div><div><font face=3D"Courier">struct implicit_thunk {</font></di=
v><div><font face=3D"Courier"><span class=3D"Apple-tab-span" style=3D"white=
-space:pre"> </span>bound f;</font></div><div><font face=3D"Courier"><span =
class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>operator typenam=
e std::result_of&lt; bound() &gt;::type ()</font></div><div><font face=3D"C=
ourier">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { return f(); }</font></d=
iv><div><font face=3D"Courier">};</font></div><div><font face=3D"Courier"><=
br></font></div><div><font face=3D"Courier">template&lt; typename bound &gt=
;</font></div><div><font face=3D"Courier">implicit_thunk&lt; typename std::=
decay&lt; bound &gt;::type &gt;</font></div><div><font face=3D"Courier">mak=
e_implicit_thunk( bound &amp;&amp; f )</font></div><div><font face=3D"Couri=
er"><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>{ retu=
rn { std::forward&lt; bound &gt;( f ) }; }</font></div></div><div><br></div=
><div><br></div><div>On Feb 27, 2014, at 3:48 AM, Andrew Tomazos &lt;<a hre=
f=3D"mailto:andrewtomazos@gmail.com">andrewtomazos@gmail.com</a>&gt; wrote:=
</div><div><br class=3D"Apple-interchange-newline"><blockquote type=3D"cite=
"><div dir=3D"ltr">On Saturday, February 22, 2014 6:21:28 AM UTC+1, myri...=
@<a href=3D"http://gmail.com">gmail.com</a> wrote:<blockquote class=3D"gmai=
l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;=
padding-left: 1ex;"><div dir=3D"ltr">I don't really know why you'd want to =
overload ?: in the first place</div></blockquote><div><br></div><div>Consid=
er a linear algebra library like:<br></div><div><br></div><div>&nbsp; &nbsp=
; matrix&lt;bool&gt; B =3D ...;</div><div>&nbsp; &nbsp; matrix&lt;float&gt;=
 X =3D ...;</div><div>&nbsp; &nbsp; matrix&lt;float&gt; Y =3D ...;</div><di=
v><br></div><div>&nbsp; &nbsp; matrix&lt;float&gt; Z =3D (B ? X : Y);</div>=
<div><br></div><div>The overloaded ?: applies the ternary operator element-=
wise.</div></div></blockquote><div><br></div><div>This simple use-case dema=
nds implementation by <font face=3D"Courier">cmove</font> instructions for =
good performance, but more sophisticated use cases would require lazy evalu=
ation. Hmm, I think the required lazy semantics could be accomplished by ex=
pression templates. So this could work.</div><br><blockquote type=3D"cite">=
<div dir=3D"ltr"><div>Granted you could just use a normal named function, b=
ut the same argument can be made against any operator overload.</div></div>=
</blockquote><div><br></div><div>Well, <font face=3D"Courier">?:</font> doe=
s give the appearance of short-circuit behavior, but in a math library, sub=
expressions usually don&rsquo;t have side effects anyway. Personally I don&=
rsquo;t think the advantage outweighs the cost. There are so many other fun=
ctions that can&rsquo;t be operators, and selection such an uncommon operat=
ion, that it wouldn't change the look-and-feel of much linear algebra code.=
</div></div><div><div><br></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=_5D962BEE-0FAC-4F50-9C55-B2AC9F6B79CD--

.