Topic: Return type deduction should be SFINAE friendly
Author: Tomasz <tomaszkam@gmail.com>
Date: Tue, 3 Nov 2015 13:42:23 -0800 (PST)
Raw View
------=_Part_5663_1059321847.1446586943228
Content-Type: multipart/alternative;
boundary="----=_Part_5664_1221562263.1446586943237"
------=_Part_5664_1221562263.1446586943237
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
*Overview:*
C++14 introduced a new feature that allows the return type to be deduced=20
from function body, via use various form of auto (auto cv ref) and=20
decltype(auto) as the return type. This feature was intended to be useful=
=20
for the library writers, as it should allow them to avoid repetition of the=
=20
expression in the decltype(expr) and return, however as in contrast to=20
decltype(expr), decltype(auto) leads to hard error (SFIAE) instead of=20
elimination of overlad (SFINAE) it was rarely useful (see not_fn case).=20
Given the fact that such user may be already experienced, this may be=20
considered as not a big problem - they should avoid using return type=20
deduction in context were SFINAE is needed.
However, I have recently realized, that the same rules is used for lambda=
=20
return type deduction and lack of SFINAE for return type deduction is not=
=20
only caused problems for library writers (experienced uses of C++), but=20
every uses of generic lambda in norma, day-to-day code.
*Motivation 1: std::function constructor*In the same time when return type=
=20
deduction was introduced, std::function<R(Args...)> interface was extended=
=20
so this object can be only constructed from the function object that is=20
callable with Args.. and return type converible to R (modulo void case).=20
That means that the std::function<int(int)> can be constructed from=20
int(*)(int), but not from std::string(*)(std::string).
That leads us to ability to write overloaded functions that will accept=20
std::function object with different signatures:
void foo(std::function<int(int)>);
void foo(std::function<std::string(std::string)>);
For the above overloads, the call=20
foo([](int x) { return x + 2; })=20
is ambiguous and will select the first overload. But if we will use a=20
generic lambda that cannot be invoked with std::string
foo([](auto x) { return x + 2; })=20
The call will end up with hard compiler error mentoring the no match for=20
call of operator+ for std::string and int. This error is produced by=20
instantiation of the lambda body with string argument that is needed do=20
determine return type.
However if we resign from uses of implicit return type deduction for lambda=
=20
and will explicitly specify it, the code will work again:
foo([](auto x) -> decltype(x+2) { return x + 2; });
Life example: http://melpon.org/wandbox/permlink/7bunImaydJ8SqyH6
*Motivation 2: writing an library code*Lets imagine that we want to write=
=20
an equivalent of not_fn(f) function that returns complement of predicate=20
not_fn(f)(args...) is equivalent to f(args..). For simplicity it will=20
support only const overload operator() and function objects (not member=20
pointers). Using decltype(auto) it could be implemented as:
template<typename F>
struct not_fn_f
{
not_fn_f(F const& f) : f_(f) {}
not_fn_f(F&& f) : f_(std::move(f)) {}
template<typename... Args>
decltype(auto) operator()(Args&&... args)
{ return f_(std::forward<Args>(args)...); }
=20
private:
F f_;
};
template<typename F>
not_fn_f<std::decay_t<F>> not_fn(F&& f)
{
return {std::forward<F>(f)};
}
Lets consider the behavior of the above code for the following functions:
void foo(std::function<bool(int)>) {}
void foo(std::function<bool(std::string)>) {}
bool is_even(int x) { return x =3D=3D 2; }
The following invocation is clearly ambiguous and calls first overload.=20
foo(&is_even);
But if the user will want to use not_fn to create an odd functor:
foo(not_fn(&is_even));
Will produce hard error from instantiation of the not_fn::operator() with=
=20
std::string. (Life example:=20
http://melpon.org/wandbox/permlink/TSVelWZOEMGFtoxT).
This problem is again caused by use of return type deduction and will not=
=20
be present if operator() will be declared using decltype(expr): (Life=20
example: http://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz)
template<typename... Args>
auto operator()(Args&&... args) const ->=20
decltype(!f_(std::forward<Args>(args)...))
To emphasis importance of the problem with lack of SFINAE on return type=20
deduction, would like to mentoin that above is present for not_fn from GCC=
=20
v5.0: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998
*Motivation 3: Concepts*There is ongoing work (TS) to introde of the=20
Concepts into C++ language. One of the main features is that they will=20
improve a lot error messages produced by the compiler. For example for=20
following code:
template<typename F, typename... Args>
concept bool Predicate =3D requires(F f, Args... args)
{ {std::forward<F>(f)(std::forward<Args>(args)...)} -> bool };
template<typename F, typename T>
requires Predicate<F&, T const&>
bool apply(F f, T const& t)
{
return f(t);
}
The invocation will the form:
apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
Will produce and short and readable error:
prog.cc: In function 'int main()':
prog.cc:18:57: error: cannot call function 'bool apply(F, const T&) [with F=
=3D main()::<lambda(int)>; T =3D std::__cxx11::basic_string<char>]'
apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
^
prog.cc:10:6: note: constraints not satisfied
bool apply(F f, T const& t)
^
prog.cc:10:6: note: concept 'Predicate<main()::<lambda(int)>&, const std:=
:__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >=
&>' was not satisfied
However if we will use generic lambda instead, without return type:
apply([](auto x) { return x =3D=3D 2; }, std::string("ala"));
The long error will be produced regarding string being not comparable with =
int. This error is produced from instantiation of lambda during check of th=
e Predicate concept, that requires to see if it is convertible to bool.
But again if we reintroduce SFINAE by using decltype(expr) we will again ge=
t the short and concise error:
apply([](auto x) -> decltype(x =3D=3D 2) { return x =3D=3D 2; }, std::strin=
g("ala"));
Life example: http://melpon.org/wandbox/permlink/7bqCglI1PAqMLxIW
*Summary:*I think that above examples shows that currently return type dedu=
ction is not only fulfilling its goal to help library writers, but it is al=
so harmful for the language, as is leads to unreadable errors occuring for =
use of lambda is normal programs, that interface with STL component. I bel=
ieve that all above problem could be changed by requiring that errors produ=
ced during instantiation requires to create and signature would lead to su=
bstitution failure instead of ill-formed programs.
*Implementability:*The main concern with above change is question if this i=
s implementable, even for compilers that support expression SFINAE.=20
However I would like to point out, that user can reproduced such functional=
ity currently, by doing a transformation of function body:
1. List every expression used in the function body in coma separated list t=
o void_t<decltype(expr1), decltype(expr2), ...>.=20
2. Every variable declaration in form T x(expr) or T x{expr} transform to T=
(expr) or T{expr} and add to above list
3. For every declration in form T x =3D initializer; transform it to expres=
sion init<T>(initializer), where init is:
template<typename T>
void init(T);
4. For every declration in form auto *cv ref* x =3D initializer; transform =
it to expression deduc_auto_*cv_ref*(initializer), where deduc_auto_*cv_ref=
* is:
template<typename T>
void deduc_auto_*cv_ref*(T *cv ref*);
Example:
template<typename T>
void deduc_auto_const_lref(T const&);
So, nearly all functionality (except using declaration) seems to be already=
supported. Futhermore in contrast to function using decltype(expr) or void=
_t in they declaration, the above list of expression found in function body=
is not required to be mangled into function name, as
we do not allow two declaration of the function auto (or other placeholder =
return type).=20
*Wording change:*Planned fix change the $7.1.6.4 p12:
Return type deduction for a function template with a placeholder in its dec=
lared type occurs when the
definition is instantiated even if the function body contains a return stat=
ement with a non-type-dependent
operand. [ Note: Therefore, any use of a specialization of the function tem=
plate will cause an implicit
instantiation. Any errors that arise from this instantiation are not in the=
immediate context of the function
type and can result in the program being ill-formed. =E2=80=94 end note ]
To:
Return type deduction for a function template with a placeholder in its dec=
lared type occurs when the
definition is instantiated even if the function body contains a return stat=
ement with a non-type-dependent
operand. [ Note: Therefore, any use of a specialization of the function tem=
plate will cause an implicit
instantiation. =E2=80=94 end note ]. Any errors that arise from this instan=
tiation shall be treated as occurring
in the immediate context of the function type.
--=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_5664_1221562263.1446586943237
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><b>Overview:</b><br>C++14 introduced a new feature that al=
lows the=20
return type to be deduced from function body, via use various form of=20
auto (auto cv ref) and decltype(auto) as the return type. This feature=20
was intended to be useful for the library writers, as it should allow=20
them to avoid repetition of the expression in the decltype(expr) and=20
return, however as in contrast to decltype(expr), decltype(auto) leads=20
to hard error (SFIAE) instead of elimination of overlad (SFINAE) it was=20
rarely useful (see not_fn case). Given the fact that such user may be=20
already experienced, this may be considered as not a big problem - they=20
should avoid using return type deduction in context were SFINAE is=20
needed.<br>However, I have recently realized, that the same rules is=20
used for lambda return type deduction and lack of SFINAE for return type
deduction is not only caused problems for library writers (experienced=20
uses of C++), but every uses of generic lambda in norma, day-to-day=20
code.<br><br><b>Motivation 1: std::function constructor<br></b>In the=20
same time when return type deduction was introduced,=20
std::function<R(Args...)> interface was extended so this object=20
can be only constructed from the function object that is callable with=20
Args.. and return type converible to R (modulo void case). That means=20
that the std::function<int(int)> can be constructed from=20
int(*)(int), but not from std::string(*)(std::string).<br>That leads us to =
ability to write overloaded functions that will accept std::function object=
with different signatures:<br><span style=3D"font-family: courier new,mono=
space;">void foo(std::function<int(int)>);<br>void foo(std::function&=
lt;std::string(std::string)>);</span><br>For the above overloads, the ca=
ll <br><span style=3D"font-family: courier new,monospace;">foo([](int x) { =
return x + 2; }) </span><br>is ambiguous and will select the first overload=
.. But if we will use a generic lambda that cannot be invoked with std::stri=
ng<br><span style=3D"font-family: courier new,monospace;">foo([](auto x) { =
return x + 2; }) <br><span style=3D"font-family: arial,sans-serif;">The
call will end up with hard compiler error mentoring the no match for=20
call of operator+ for std::string and int. This error is produced by=20
instantiation of the lambda body with string argument that is needed do=20
determine return type.<br>However if we resign from uses of implicit=20
return type deduction for lambda and will explicitly specify it, the=20
code will work again:<br><span style=3D"font-family: courier new,monospace;=
">foo([](auto x) -> decltype(x+2) { return x + 2; });</span><br>Life exa=
mple: <a href=3D"http://melpon.org/wandbox/permlink/7bunImaydJ8SqyH6">http:=
//melpon.org/wandbox/permlink/7bunImaydJ8SqyH6</a><br><br><b>Motivation 2: =
writing an library code<br></b>Lets
imagine that we want to write an equivalent of not_fn(f) function that=20
returns complement of predicate not_fn(f)(args...) is equivalent to=20
f(args..). For simplicity it will support only const overload operator()
and function objects (not member pointers). Using decltype(auto) it=20
could be implemented as:<br><span style=3D"font-family: courier new,monospa=
ce;">template<typename F><br>struct not_fn_f<br>{<br>=C2=A0 not_fn_f(=
F const& f) : f_(f) {}<br>=C2=A0 not_fn_f(F&& f) : f_(std::move=
(f)) {}<br><br>=C2=A0 template<typename... Args><br>=C2=A0 decltype(a=
uto) operator()(Args&&... args)<br>=C2=A0 { return f_(std::forward&=
lt;Args>(args)...); }<br>=C2=A0=C2=A0=C2=A0 <br>private:<br>=C2=A0 F f_;=
<br>};</span><br><br><span style=3D"font-family: courier new,monospace;">te=
mplate<typename F><br>not_fn_f<std::decay_t<F>> not_fn(F&=
amp;& f)<br>{<br>=C2=A0=C2=A0=C2=A0 return {std::forward<F>(f)};<=
br>}</span><br>Lets consider the behavior of the above code for the followi=
ng functions:<br><span style=3D"font-family: courier new,monospace;">void f=
oo(std::function<bool(int)>) {}<br>void foo(std::function<bool(std=
::string)>) {}<br><br>bool is_even(int x) { return x =3D=3D 2; }</span><=
br>The following invocation is clearly ambiguous and calls first overload. =
<br><span style=3D"font-family: courier new,monospace;">foo(&is_even);<=
/span><br>But if the user will want to use not_fn to create an odd functor:=
</span><br>foo(not_fn(&is_even));<br><span style=3D"font-family: arial,=
sans-serif;">Will produce hard error from instantiation of the not_fn::oper=
ator() with std::string. (Life example: </span><a href=3D"http://melpon.org=
/wandbox/permlink/TSVelWZOEMGFtoxT">http://melpon.org/wandbox/permlink/TSVe=
lWZOEMGFtoxT</a>).<br><span style=3D"font-family: arial,sans-serif;">This
problem is again caused by use of return type deduction and will not be
present if operator() will be declared using decltype(expr): (Life
example: <a href=3D"http://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz">h=
ttp://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz</a>)<br></span>template&=
lt;typename... Args><br>auto operator()(Args&&... args) const -&=
gt; decltype(!f_(std::forward<Args>(args)...))<br><br><font face=3D"a=
rial,sans-serif">To
emphasis importance of the problem with lack of SFINAE on return type=20
deduction, would like to mentoin that above is present for not_fn from=20
GCC v5.0: <a href=3D"https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998">=
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998</a></font><br><br></sp=
an><b>Motivation 3: Concepts<br></b>There
is ongoing work (TS) to introde of the Concepts into C++ language. One=20
of the main features is that they will improve a lot error messages=20
produced by the compiler. For example for following code:<b><br></b><span s=
tyle=3D"font-family: courier new,monospace;">template<typename F, typena=
me... Args><br>concept bool Predicate =3D requires(F f, Args... args)<br=
>{ {std::forward<F>(f)(std::forward<Args>(args)...)} -> bool=
};<br><br>template<typename F, typename T><br>=C2=A0 requires Predic=
ate<F&, T const&><br>bool apply(F f, T const& t)<br>{<br>=
=C2=A0 return f(t);<br>}</span><b><br></b>The invocation will the form:<br>=
<span style=3D"font-family: courier new,monospace;">apply([](int x) { retur=
n x =3D=3D 2; }, std::string("ala"));<br><font face=3D"arial,sans=
-serif">Will produce and short and readable error:<br></font></span><pre da=
ta-text=3D"prog.cc: In function 'int main()':
prog.cc:18:57: error: cannot call function 'bool apply(F, const T&)=
[with F =3D main()::<lambda(int)>; T =3D std::__cxx11::basic_string&=
lt;char>]'
apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
^
prog.cc:10:6: note: constraints not satisfied
bool apply(F f, T const& t)
^
prog.cc:10:6: note: concept 'Predicate<main()::<lambda(int)>=
&, const std::__cxx11::basic_string<char, std::char_traits<char&g=
t;, std::allocator<char> >&>' was not satisfied
" data-type=3D"CompilerMessageE" class=3D"CompilerMessageE">prog.cc: In fun=
ction 'int main()':
prog.cc:18:57: error: cannot call function 'bool apply(F, const T&)=
[with F =3D main()::<lambda(int)>; T =3D std::__cxx11::basic_string&=
lt;char>]'
apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
^
prog.cc:10:6: note: constraints not satisfied
bool apply(F f, T const& t)
^
prog.cc:10:6: note: concept 'Predicate<main()::<lambda(int)>=
&, const std::__cxx11::basic_string<char, std::char_traits<char&g=
t;, std::allocator<char> >&>' was not satisfied<br><spa=
n style=3D"font-family: arial,sans-serif;">However if we will use generic l=
ambda instead, without return type:<br><span style=3D"font-family: courier =
new,monospace;">apply([](auto x) { return x =3D=3D 2; }, std::string("=
ala"));</span><br>The long error will be produced regarding string bei=
ng not comparable with int. This error is produced from instantiation of la=
mbda during check of the Predicate concept, that requires to see if it is c=
onvertible to bool.<br>But again if we reintroduce SFINAE by using decltype=
(expr) we will again get the short and concise error:<br><span style=3D"fon=
t-family: courier new,monospace;">apply([](auto x) -> decltype(x =3D=3D =
2) { return x =3D=3D 2; }, std::string("ala"));</span><br>Life ex=
ample: <a href=3D"http://melpon.org/wandbox/permlink/7bqCglI1PAqMLxIW">http=
://melpon.org/wandbox/permlink/7bqCglI1PAqMLxIW</a><br><br><b>Summary:<br><=
/b>I think that above examples shows that currently return type deduction i=
s not only fulfilling its goal to help library writers, but it is also harm=
ful for the language, as is leads to unreadable errors occuring for use of =
lambda is normal programs, that interface with STL component. I believe th=
at all above problem could be changed by requiring that errors produced dur=
ing instantiation requires to create and signature would lead to substitut=
ion failure instead of ill-formed programs.<br><br><b>Implementability:<br>=
</b>The main concern with above change is question if this is implementable=
, even for compilers that support expression SFINAE. <br><br>However I woul=
d like to point out, that user can reproduced such functionality currently,=
by doing a transformation of function body:<br>1. List every expression us=
ed in the function body in coma separated list to void_t<decltype(expr1)=
, decltype(expr2), ...>. <br>2. Every variable declaration in form T x(e=
xpr) or T x{expr} transform to T(expr) or T{expr} and add to above list<br>=
3. For every declration in form T x =3D initializer; transform it to expres=
sion init<T>(initializer), where init is:<br><span style=3D"font-fami=
ly: courier new,monospace;">template<typename T><br>void init(T);</sp=
an><br></span><span style=3D"font-family: arial,sans-serif;">4. For every d=
eclration in form auto <i>cv ref</i> x =3D initializer; transform it to exp=
ression deduc_auto_<i>cv_ref</i>(initializer), where </span><span style=3D"=
font-family: arial,sans-serif;"><span style=3D"font-family: arial,sans-seri=
f;">deduc_auto_<i>cv_ref</i></span> is:<br></span><span style=3D"font-famil=
y: arial,sans-serif;"></span><span style=3D"font-family: courier new,monosp=
ace;">template<typename T><br>void deduc_auto_<i>cv_ref</i>(T <i>cv r=
ef</i>);<br><font face=3D"arial,sans-serif">Example:<br></font></span><span=
style=3D"font-family: courier new,monospace;">template<typename T><b=
r>void deduc_auto_const_lref(T const&);<br><br><span style=3D"font-fami=
ly: arial,sans-serif;">So, nearly all functionality (except using declarati=
on) seems to be already supported. Futhermore in contrast to function using=
decltype(expr) or void_t in they declaration, the above list of expression=
found in function body is not required to be mangled into function name, a=
s<br>we do not allow two declaration of the function auto (or other placeho=
lder return type).</span> <br><br></span><span style=3D"font-family: arial,=
sans-serif;"><b>Wording change:<br></b>Planned fix change the $7.1.6.4 p12:=
<br>Return type deduction for a function template with a placeholder in its=
declared type occurs when the<br>definition is instantiated even if the fu=
nction body contains a return statement with a non-type-dependent<br>operan=
d. [ Note: Therefore, any use of a specialization of the function template =
will cause an implicit<br>instantiation. Any errors that arise from this in=
stantiation are not in the immediate context of the function<br>type and ca=
n result in the program being ill-formed. =E2=80=94 end note ]<br><br>To:<b=
r>Return type deduction for a function template with a placeholder in its d=
eclared type occurs when the<br>definition is instantiated even if the func=
tion body contains a return statement with a non-type-dependent<br>operand.=
[ Note: Therefore, any use of a specialization of the function template wi=
ll cause an implicit<br>instantiation. =E2=80=94 end note ]. Any errors tha=
t arise from this instantiation shall be treated as occurring<br>=C2=A0in t=
he immediate context of the function type.<b><br></b></span></pre></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5664_1221562263.1446586943237--
------=_Part_5663_1059321847.1446586943228--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 3 Nov 2015 17:06:58 -0800 (PST)
Raw View
------=_Part_2094_1179144642.1446599218396
Content-Type: multipart/alternative;
boundary="----=_Part_2095_1190827719.1446599218397"
------=_Part_2095_1190827719.1446599218397
Content-Type: text/plain; charset=UTF-8
If you're going to go that far, you may as well declare that SFINAE is
automatic for every template function. Why limit it to just return type
deduction, after all? How many times have we wanted automatic SFINAE, where
any error just mean that the template substitution failed?
One reason we don't do that, why we explicitly limit SFINAE to
parameters/return types, is so that we don't get false positives. If it
gets past the signature, then any errors that happen ought to be real,
genuine errors that a user has to face. That is, someone did something
*wrong*.
If you give someone a type and they try to default construct it and that
fails, then either your template function did something wrong or the user
passed an inappropriate type. Either way, it should hard error out. We
(will) have concepts to check things like that in the future, so having a
hard error is the right thing. The declaration should not simply disappear.
--
---
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_2095_1190827719.1446599218397
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">If you're going to go that far, you may as well declar=
e that SFINAE is automatic for every template function. Why limit it to jus=
t return type deduction, after all? How many times have we wanted automatic=
SFINAE, where any error just mean that the template substitution failed?<b=
r><br>One reason we don't do that, why we explicitly limit SFINAE to pa=
rameters/return types, is so that we don't get false positives. If it g=
ets past the signature, then any errors that happen ought to be real, genui=
ne errors that a user has to face. That is, someone did something <i>wrong<=
/i>.<br><br>If you give someone a type and they try to default construct it=
and that fails, then either your template function did something wrong or =
the user passed an inappropriate type. Either way, it should hard error out=
.. We (will) have concepts to check things like that in the future, so havin=
g a hard error is the right thing. The declaration should not simply disapp=
ear.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2095_1190827719.1446599218397--
------=_Part_2094_1179144642.1446599218396--
.
Author: Tomasz <tomaszkam@gmail.com>
Date: Tue, 3 Nov 2015 22:12:38 -0800 (PST)
Raw View
------=_Part_6146_288551192.1446617559151
Content-Type: multipart/alternative;
boundary="----=_Part_6147_196485169.1446617559151"
------=_Part_6147_196485169.1446617559151
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytkownik Nicol Bo=
las=20
napisa=C5=82:
>
> If you're going to go that far, you may as well declare that SFINAE is=20
> automatic for every template function. Why limit it to just return type=
=20
> deduction, after all? How many times have we wanted automatic SFINAE, whe=
re=20
> any error just mean that the template substitution failed?
>
> Because returntype deduction is used for generic lambda and causes=20
problems to blow up into programmer face, even for simple cases.
=20
> One reason we don't do that, why we explicitly limit SFINAE to=20
> parameters/return types, is so that we don't get false positives. If it=
=20
> gets past the signature, then any errors that happen ought to be real,=20
> genuine errors that a user has to face. That is, someone did something=20
> *wrong*.
>
And I am requesting and SFINAE for return type for function using return=20
type deduction.
=20
>
> If you give someone a type and they try to default construct it and that=
=20
> fails, then either your template function did something wrong or the user=
=20
> passed an inappropriate type. Either way, it should hard error out. We=20
> (will) have concepts to check things like that in the future, so having a=
=20
> hard error is the right thing. The declaration should not simply disappea=
r.
>
Have you checked Motivation 3 regarding the concepts. Lack of SFINAE for=20
return type deduction essentially breaks concept for generic lambda uses,=
=20
And I do not think that users will constrain every lambda they will write.=
=20
--=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_6147_196485169.1446617559151
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BC=
ytkownik Nicol Bolas napisa=C5=82:<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">If you're going to go that far, you may as well =
declare that SFINAE is automatic for every template function. Why limit it =
to just return type deduction, after all? How many times have we wanted aut=
omatic SFINAE, where any error just mean that the template substitution fai=
led?<br><br></div></blockquote><div>Because returntype deduction is used fo=
r generic lambda and causes problems to blow up into programmer face, even =
for simple cases.<br>=C2=A0</div><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">One reason we don't do that, why we explicitly limi=
t SFINAE to parameters/return types, is so that we don't get false posi=
tives. If it gets past the signature, then any errors that happen ought to =
be real, genuine errors that a user has to face. That is, someone did somet=
hing <i>wrong</i>.<br></div></blockquote><div>And I am requesting and SFINA=
E for return type for function using return type deduction.<br>=C2=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br>If you gi=
ve someone a type and they try to default construct it and that fails, then=
either your template function did something wrong or the user passed an in=
appropriate type. Either way, it should hard error out. We (will) have conc=
epts to check things like that in the future, so having a hard error is the=
right thing. The declaration should not simply disappear.<br></div></block=
quote><div><br>Have you checked Motivation 3 regarding the concepts. Lack o=
f SFINAE for return type deduction essentially breaks concept for generic l=
ambda uses, And I do not think that users will constrain every lambda they =
will write. <br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_6147_196485169.1446617559151--
------=_Part_6146_288551192.1446617559151--
.
Author: Mathias Gaunard <mathias@gaunard.com>
Date: Wed, 4 Nov 2015 12:30:30 +0000
Raw View
--001a11c3cb440e83f00523b62d86
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
While that would indeed be practical (I currently tend to use macros to
avoid the repetition required), I think there is also value is having a
function where the return type is automatically deduced while the body is
*not* part of the declaration and SFINAE context.
Making it part of the declaration is also a breaking change which is
undesirable.
I therefore suggest you introduce a different syntax for this.
On Tue, Nov 3, 2015 at 9:42 PM, Tomasz <tomaszkam@gmail.com> wrote:
> *Overview:*
> C++14 introduced a new feature that allows the return type to be deduced
> from function body, via use various form of auto (auto cv ref) and
> decltype(auto) as the return type. This feature was intended to be useful
> for the library writers, as it should allow them to avoid repetition of t=
he
> expression in the decltype(expr) and return, however as in contrast to
> decltype(expr), decltype(auto) leads to hard error (SFIAE) instead of
> elimination of overlad (SFINAE) it was rarely useful (see not_fn case).
> Given the fact that such user may be already experienced, this may be
> considered as not a big problem - they should avoid using return type
> deduction in context were SFINAE is needed.
> However, I have recently realized, that the same rules is used for lambda
> return type deduction and lack of SFINAE for return type deduction is not
> only caused problems for library writers (experienced uses of C++), but
> every uses of generic lambda in norma, day-to-day code.
>
>
> *Motivation 1: std::function constructor*In the same time when return
> type deduction was introduced, std::function<R(Args...)> interface was
> extended so this object can be only constructed from the function object
> that is callable with Args.. and return type converible to R (modulo void
> case). That means that the std::function<int(int)> can be constructed fro=
m
> int(*)(int), but not from std::string(*)(std::string).
> That leads us to ability to write overloaded functions that will accept
> std::function object with different signatures:
> void foo(std::function<int(int)>);
> void foo(std::function<std::string(std::string)>);
> For the above overloads, the call
> foo([](int x) { return x + 2; })
> is ambiguous and will select the first overload. But if we will use a
> generic lambda that cannot be invoked with std::string
> foo([](auto x) { return x + 2; })
> The call will end up with hard compiler error mentoring the no match for
> call of operator+ for std::string and int. This error is produced by
> instantiation of the lambda body with string argument that is needed do
> determine return type.
> However if we resign from uses of implicit return type deduction for
> lambda and will explicitly specify it, the code will work again:
> foo([](auto x) -> decltype(x+2) { return x + 2; });
> Life example: http://melpon.org/wandbox/permlink/7bunImaydJ8SqyH6
>
>
> *Motivation 2: writing an library code*Lets imagine that we want to write
> an equivalent of not_fn(f) function that returns complement of predicate
> not_fn(f)(args...) is equivalent to f(args..). For simplicity it will
> support only const overload operator() and function objects (not member
> pointers). Using decltype(auto) it could be implemented as:
> template<typename F>
> struct not_fn_f
> {
> not_fn_f(F const& f) : f_(f) {}
> not_fn_f(F&& f) : f_(std::move(f)) {}
>
> template<typename... Args>
> decltype(auto) operator()(Args&&... args)
> { return f_(std::forward<Args>(args)...); }
>
> private:
> F f_;
> };
>
> template<typename F>
> not_fn_f<std::decay_t<F>> not_fn(F&& f)
> {
> return {std::forward<F>(f)};
> }
> Lets consider the behavior of the above code for the following functions:
> void foo(std::function<bool(int)>) {}
> void foo(std::function<bool(std::string)>) {}
>
> bool is_even(int x) { return x =3D=3D 2; }
> The following invocation is clearly ambiguous and calls first overload.
> foo(&is_even);
> But if the user will want to use not_fn to create an odd functor:
> foo(not_fn(&is_even));
> Will produce hard error from instantiation of the not_fn::operator() with
> std::string. (Life example:
> http://melpon.org/wandbox/permlink/TSVelWZOEMGFtoxT).
> This problem is again caused by use of return type deduction and will not
> be present if operator() will be declared using decltype(expr): (Life
> example: http://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz)
> template<typename... Args>
> auto operator()(Args&&... args) const ->
> decltype(!f_(std::forward<Args>(args)...))
>
> To emphasis importance of the problem with lack of SFINAE on return type
> deduction, would like to mentoin that above is present for not_fn from GC=
C
> v5.0: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998
>
>
> *Motivation 3: Concepts*There is ongoing work (TS) to introde of the
> Concepts into C++ language. One of the main features is that they will
> improve a lot error messages produced by the compiler. For example for
> following code:
> template<typename F, typename... Args>
> concept bool Predicate =3D requires(F f, Args... args)
> { {std::forward<F>(f)(std::forward<Args>(args)...)} -> bool };
>
> template<typename F, typename T>
> requires Predicate<F&, T const&>
> bool apply(F f, T const& t)
> {
> return f(t);
> }
> The invocation will the form:
> apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
> Will produce and short and readable error:
>
> prog.cc: In function 'int main()':
> prog.cc:18:57: error: cannot call function 'bool apply(F, const T&) [with=
F =3D main()::<lambda(int)>; T =3D std::__cxx11::basic_string<char>]'
> apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
> ^
> prog.cc:10:6: note: constraints not satisfied
> bool apply(F f, T const& t)
> ^
> prog.cc:10:6: note: concept 'Predicate<main()::<lambda(int)>&, const st=
d::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>=
>&>' was not satisfied
> However if we will use generic lambda instead, without return type:
> apply([](auto x) { return x =3D=3D 2; }, std::string("ala"));
> The long error will be produced regarding string being not comparable wit=
h int. This error is produced from instantiation of lambda during check of =
the Predicate concept, that requires to see if it is convertible to bool.
> But again if we reintroduce SFINAE by using decltype(expr) we will again =
get the short and concise error:
> apply([](auto x) -> decltype(x =3D=3D 2) { return x =3D=3D 2; }, std::str=
ing("ala"));
> Life example: http://melpon.org/wandbox/permlink/7bqCglI1PAqMLxIW
>
>
> *Summary:*I think that above examples shows that currently return type de=
duction is not only fulfilling its goal to help library writers, but it is =
also harmful for the language, as is leads to unreadable errors occuring fo=
r use of lambda is normal programs, that interface with STL component. I b=
elieve that all above problem could be changed by requiring that errors pro=
duced during instantiation requires to create and signature would lead to =
substitution failure instead of ill-formed programs.
>
>
> *Implementability:*The main concern with above change is question if this=
is implementable, even for compilers that support expression SFINAE.
>
> However I would like to point out, that user can reproduced such function=
ality currently, by doing a transformation of function body:
> 1. List every expression used in the function body in coma separated list=
to void_t<decltype(expr1), decltype(expr2), ...>.
> 2. Every variable declaration in form T x(expr) or T x{expr} transform to=
T(expr) or T{expr} and add to above list
> 3. For every declration in form T x =3D initializer; transform it to expr=
ession init<T>(initializer), where init is:
> template<typename T>
> void init(T);
> 4. For every declration in form auto *cv ref* x =3D initializer; transfor=
m it to expression deduc_auto_*cv_ref*(initializer), where deduc_auto_*cv_r=
ef* is:
> template<typename T>
> void deduc_auto_*cv_ref*(T *cv ref*);
> Example:
> template<typename T>
> void deduc_auto_const_lref(T const&);
>
> So, nearly all functionality (except using declaration) seems to be alrea=
dy supported. Futhermore in contrast to function using decltype(expr) or vo=
id_t in they declaration, the above list of expression found in function bo=
dy is not required to be mangled into function name, as
> we do not allow two declaration of the function auto (or other placeholde=
r return type).
>
>
> *Wording change:*Planned fix change the $7.1.6.4 p12:
> Return type deduction for a function template with a placeholder in its d=
eclared type occurs when the
> definition is instantiated even if the function body contains a return st=
atement with a non-type-dependent
> operand. [ Note: Therefore, any use of a specialization of the function t=
emplate will cause an implicit
> instantiation. Any errors that arise from this instantiation are not in t=
he immediate context of the function
> type and can result in the program being ill-formed. =E2=80=94 end note ]
>
> To:
> Return type deduction for a function template with a placeholder in its d=
eclared type occurs when the
> definition is instantiated even if the function body contains a return st=
atement with a non-type-dependent
> operand. [ Note: Therefore, any use of a specialization of the function t=
emplate will cause an implicit
> instantiation. =E2=80=94 end note ]. Any errors that arise from this inst=
antiation shall be treated as occurring
> in the immediate context of the function type.
>
> --
>
> ---
> 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/.
>
--=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/.
--001a11c3cb440e83f00523b62d86
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">While that would indeed be practical (I currently tend to =
use macros to avoid the repetition required), I think there is also value i=
s having a function where the return type is automatically deduced while th=
e body is *not* part of the declaration and SFINAE context.<div><br></div><=
div>Making it part of the declaration is also a breaking change which is un=
desirable.</div><div><br></div><div>I therefore suggest you introduce a dif=
ferent syntax for this.</div><div class=3D"gmail_extra"><br><div class=3D"g=
mail_quote">On Tue, Nov 3, 2015 at 9:42 PM, Tomasz <span dir=3D"ltr"><<a=
href=3D"mailto:tomaszkam@gmail.com" target=3D"_blank">tomaszkam@gmail.com<=
/a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:=
0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><b=
>Overview:</b><br>C++14 introduced a new feature that allows the=20
return type to be deduced from function body, via use various form of=20
auto (auto cv ref) and decltype(auto) as the return type. This feature=20
was intended to be useful for the library writers, as it should allow=20
them to avoid repetition of the expression in the decltype(expr) and=20
return, however as in contrast to decltype(expr), decltype(auto) leads=20
to hard error (SFIAE) instead of elimination of overlad (SFINAE) it was=20
rarely useful (see not_fn case). Given the fact that such user may be=20
already experienced, this may be considered as not a big problem - they=20
should avoid using return type deduction in context were SFINAE is=20
needed.<br>However, I have recently realized, that the same rules is=20
used for lambda return type deduction and lack of SFINAE for return type
deduction is not only caused problems for library writers (experienced=20
uses of C++), but every uses of generic lambda in norma, day-to-day=20
code.<br><br><b>Motivation 1: std::function constructor<br></b>In the=20
same time when return type deduction was introduced,=20
std::function<R(Args...)> interface was extended so this object=20
can be only constructed from the function object that is callable with=20
Args.. and return type converible to R (modulo void case). That means=20
that the std::function<int(int)> can be constructed from=20
int(*)(int), but not from std::string(*)(std::string).<br>That leads us to =
ability to write overloaded functions that will accept std::function object=
with different signatures:<br><span style=3D"font-family:courier new,monos=
pace">void foo(std::function<int(int)>);<br>void foo(std::function<=
;std::string(std::string)>);</span><br>For the above overloads, the call=
<br><span style=3D"font-family:courier new,monospace">foo([](int x) { retu=
rn x + 2; }) </span><br>is ambiguous and will select the first overload. Bu=
t if we will use a generic lambda that cannot be invoked with std::string<b=
r><span style=3D"font-family:courier new,monospace">foo([](auto x) { return=
x + 2; }) <br><span style=3D"font-family:arial,sans-serif">The
call will end up with hard compiler error mentoring the no match for=20
call of operator+ for std::string and int. This error is produced by=20
instantiation of the lambda body with string argument that is needed do=20
determine return type.<br>However if we resign from uses of implicit=20
return type deduction for lambda and will explicitly specify it, the=20
code will work again:<br><span style=3D"font-family:courier new,monospace">=
foo([](auto x) -> decltype(x+2) { return x + 2; });</span><br>Life examp=
le: <a href=3D"http://melpon.org/wandbox/permlink/7bunImaydJ8SqyH6" target=
=3D"_blank">http://melpon.org/wandbox/permlink/7bunImaydJ8SqyH6</a><br><br>=
<b>Motivation 2: writing an library code<br></b>Lets
imagine that we want to write an equivalent of not_fn(f) function that=20
returns complement of predicate not_fn(f)(args...) is equivalent to=20
f(args..). For simplicity it will support only const overload operator()
and function objects (not member pointers). Using decltype(auto) it=20
could be implemented as:<br><span style=3D"font-family:courier new,monospac=
e">template<typename F><br>struct not_fn_f<br>{<br>=C2=A0 not_fn_f(F =
const& f) : f_(f) {}<br>=C2=A0 not_fn_f(F&& f) : f_(std::move(f=
)) {}<br><br>=C2=A0 template<typename... Args><br>=C2=A0 decltype(aut=
o) operator()(Args&&... args)<br>=C2=A0 { return f_(std::forward<=
;Args>(args)...); }<br>=C2=A0=C2=A0=C2=A0 <br>private:<br>=C2=A0 F f_;<b=
r>};</span><br><br><span style=3D"font-family:courier new,monospace">templa=
te<typename F><br>not_fn_f<std::decay_t<F>> not_fn(F&=
& f)<br>{<br>=C2=A0=C2=A0=C2=A0 return {std::forward<F>(f)};<br>}=
</span><br>Lets consider the behavior of the above code for the following f=
unctions:<br><span style=3D"font-family:courier new,monospace">void foo(std=
::function<bool(int)>) {}<br>void foo(std::function<bool(std::stri=
ng)>) {}<br><br>bool is_even(int x) { return x =3D=3D 2; }</span><br>The=
following invocation is clearly ambiguous and calls first overload. <br><s=
pan style=3D"font-family:courier new,monospace">foo(&is_even);</span><b=
r>But if the user will want to use not_fn to create an odd functor:</span><=
br>foo(not_fn(&is_even));<br><span style=3D"font-family:arial,sans-seri=
f">Will produce hard error from instantiation of the not_fn::operator() wit=
h std::string. (Life example: </span><a href=3D"http://melpon.org/wandbox/p=
ermlink/TSVelWZOEMGFtoxT" target=3D"_blank">http://melpon.org/wandbox/perml=
ink/TSVelWZOEMGFtoxT</a>).<br><span style=3D"font-family:arial,sans-serif">=
This
problem is again caused by use of return type deduction and will not be
present if operator() will be declared using decltype(expr): (Life
example: <a href=3D"http://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz" t=
arget=3D"_blank">http://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz</a>)<b=
r></span>template<typename... Args><br>auto operator()(Args&&=
.... args) const -> decltype(!f_(std::forward<Args>(args)...))<br><=
br><font face=3D"arial,sans-serif">To
emphasis importance of the problem with lack of SFINAE on return type=20
deduction, would like to mentoin that above is present for not_fn from=20
GCC v5.0: <a href=3D"https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998" =
target=3D"_blank">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998</a><=
/font><br><br></span><b>Motivation 3: Concepts<br></b>There
is ongoing work (TS) to introde of the Concepts into C++ language. One=20
of the main features is that they will improve a lot error messages=20
produced by the compiler. For example for following code:<b><br></b><span s=
tyle=3D"font-family:courier new,monospace">template<typename F, typename=
.... Args><br>concept bool Predicate =3D requires(F f, Args... args)<br>{=
{std::forward<F>(f)(std::forward<Args>(args)...)} -> bool }=
;<br><br>template<typename F, typename T><br>=C2=A0 requires Predicat=
e<F&, T const&><br>bool apply(F f, T const& t)<br>{<br>=
=C2=A0 return f(t);<br>}</span><b><br></b>The invocation will the form:<br>=
<span style=3D"font-family:courier new,monospace">apply([](int x) { return =
x =3D=3D 2; }, std::string("ala"));<br><font face=3D"arial,sans-s=
erif">Will produce and short and readable error:<br></font></span><pre>prog=
..cc: In function 'int main()':
prog.cc:18:57: error: cannot call function 'bool apply(F, const T&)=
[with F =3D main()::<lambda(int)>; T =3D std::__cxx11::basic_string&=
lt;char>]'
apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
^
prog.cc:10:6: note: constraints not satisfied
bool apply(F f, T const& t)
^
prog.cc:10:6: note: concept 'Predicate<main()::<lambda(int)>=
&, const std::__cxx11::basic_string<char, std::char_traits<char&g=
t;, std::allocator<char> >&>' was not satisfied<br><spa=
n style=3D"font-family:arial,sans-serif">However if we will use generic lam=
bda instead, without return type:<br><span style=3D"font-family:courier new=
,monospace">apply([](auto x) { return x =3D=3D 2; }, std::string("ala&=
quot;));</span><br>The long error will be produced regarding string being n=
ot comparable with int. This error is produced from instantiation of lambda=
during check of the Predicate concept, that requires to see if it is conve=
rtible to bool.<br>But again if we reintroduce SFINAE by using decltype(exp=
r) we will again get the short and concise error:<br><span style=3D"font-fa=
mily:courier new,monospace">apply([](auto x) -> decltype(x =3D=3D 2) { r=
eturn x =3D=3D 2; }, std::string("ala"));</span><br>Life example:=
<a href=3D"http://melpon.org/wandbox/permlink/7bqCglI1PAqMLxIW" target=3D"=
_blank">http://melpon.org/wandbox/permlink/7bqCglI1PAqMLxIW</a><br><br><b>S=
ummary:<br></b>I think that above examples shows that currently return type=
deduction is not only fulfilling its goal to help library writers, but it =
is also harmful for the language, as is leads to unreadable errors occuring=
for use of lambda is normal programs, that interface with STL component. =
I believe that all above problem could be changed by requiring that errors =
produced during instantiation requires to create and signature would lead =
to substitution failure instead of ill-formed programs.<br><br><b>Implement=
ability:<br></b>The main concern with above change is question if this is i=
mplementable, even for compilers that support expression SFINAE. <br><br>Ho=
wever I would like to point out, that user can reproduced such functionalit=
y currently, by doing a transformation of function body:<br>1. List every e=
xpression used in the function body in coma separated list to void_t<dec=
ltype(expr1), decltype(expr2), ...>. <br>2. Every variable declaration i=
n form T x(expr) or T x{expr} transform to T(expr) or T{expr} and add to ab=
ove list<br>3. For every declration in form T x =3D initializer; transform =
it to expression init<T>(initializer), where init is:<br><span style=
=3D"font-family:courier new,monospace">template<typename T><br>void i=
nit(T);</span><br></span><span style=3D"font-family:arial,sans-serif">4. Fo=
r every declration in form auto <i>cv ref</i> x =3D initializer; transform =
it to expression deduc_auto_<i>cv_ref</i>(initializer), where </span><span =
style=3D"font-family:arial,sans-serif"><span style=3D"font-family:arial,san=
s-serif">deduc_auto_<i>cv_ref</i></span> is:<br></span><span style=3D"font-=
family:arial,sans-serif"></span><span style=3D"font-family:courier new,mono=
space">template<typename T><br>void deduc_auto_<i>cv_ref</i>(T <i>cv =
ref</i>);<br><font face=3D"arial,sans-serif">Example:<br></font></span><spa=
n style=3D"font-family:courier new,monospace">template<typename T><br=
>void deduc_auto_const_lref(T const&);<br><br><span style=3D"font-famil=
y:arial,sans-serif">So, nearly all functionality (except using declaration)=
seems to be already supported. Futhermore in contrast to function using de=
cltype(expr) or void_t in they declaration, the above list of expression fo=
und in function body is not required to be mangled into function name, as<b=
r>we do not allow two declaration of the function auto (or other placeholde=
r return type).</span> <br><br></span><span style=3D"font-family:arial,sans=
-serif"><b>Wording change:<br></b>Planned fix change the $7.1.6.4 p12:<br>R=
eturn type deduction for a function template with a placeholder in its decl=
ared type occurs when the<br>definition is instantiated even if the functio=
n body contains a return statement with a non-type-dependent<br>operand. [ =
Note: Therefore, any use of a specialization of the function template will =
cause an implicit<br>instantiation. Any errors that arise from this instant=
iation are not in the immediate context of the function<br>type and can res=
ult in the program being ill-formed. =E2=80=94 end note ]<br><br>To:<br>Ret=
urn type deduction for a function template with a placeholder in its declar=
ed type occurs when the<br>definition is instantiated even if the function =
body contains a return statement with a non-type-dependent<br>operand. [ No=
te: Therefore, any use of a specialization of the function template will ca=
use an implicit<br>instantiation. =E2=80=94 end note ]. Any errors that ari=
se from this instantiation shall be treated as occurring<br>=C2=A0in the im=
mediate context of the function type.<span class=3D"HOEnZb"><font color=3D"=
#888888"><b><br></b></font></span></span></pre></div><span class=3D"HOEnZb"=
><font color=3D"#888888">
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</font></span></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c3cb440e83f00523b62d86--
.
Author: Tomasz <tomaszkam@gmail.com>
Date: Wed, 4 Nov 2015 04:45:15 -0800 (PST)
Raw View
------=_Part_1149_309039405.1446641115315
Content-Type: multipart/alternative;
boundary="----=_Part_1150_901411322.1446641115326"
------=_Part_1150_901411322.1446641115326
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
W dniu =C5=9Broda, 4 listopada 2015 13:30:34 UTC+1 u=C5=BCytkownik Mathias =
Gaunard=20
napisa=C5=82:
>
> While that would indeed be practical (I currently tend to use macros to=
=20
> avoid the repetition required), I think there is also value is having a=
=20
> function where the return type is automatically deduced while the body is=
=20
> *not* part of the declaration and SFINAE context.
>
> Making it part of the declaration is also a breaking change which is=20
> undesirable.
>
I fail to see how requiring that failure in instantiation required to=20
deduce a return type an substitution failure will be breaking change. Now=
=20
for every declared function template that uses return type deduction, there=
=20
are two possible output:
1. For every set of arguments substituted in program, instantiation does=20
not fail and whole program is valid. In this case, proposed change will=20
essentially do nothing, as there are now failures in instantiation.
2. For at least one set of arguments, substitution fails. The program is=20
ill-formed according $7.1.6.4 p12, so change is not breaking (you cannot=20
break invalid programs).
Also given above possible outputs, I do not see any value in producing hard=
=20
error from function instantiation in valid programs.
Furthermore my proposition, requires that instantiation errors should be=20
threated as occurring in context in immediate context of function type, but=
=20
does include function body as part of declaration (see comment about=20
mangling in implementation section).
> I therefore suggest you introduce a different syntax for this.
>
Will not help lambda, unless we change rules for lambda default return type=
=20
deduction.
=20
>
> On Tue, Nov 3, 2015 at 9:42 PM, Tomasz <toma...@gmail.com <javascript:>>=
=20
> wrote:
>
>> *Overview:*
>> C++14 introduced a new feature that allows the return type to be deduced=
=20
>> from function body, via use various form of auto (auto cv ref) and=20
>> decltype(auto) as the return type. This feature was intended to be usefu=
l=20
>> for the library writers, as it should allow them to avoid repetition of =
the=20
>> expression in the decltype(expr) and return, however as in contrast to=
=20
>> decltype(expr), decltype(auto) leads to hard error (SFIAE) instead of=20
>> elimination of overlad (SFINAE) it was rarely useful (see not_fn case).=
=20
>> Given the fact that such user may be already experienced, this may be=20
>> considered as not a big problem - they should avoid using return type=20
>> deduction in context were SFINAE is needed.
>> However, I have recently realized, that the same rules is used for lambd=
a=20
>> return type deduction and lack of SFINAE for return type deduction is no=
t=20
>> only caused problems for library writers (experienced uses of C++), but=
=20
>> every uses of generic lambda in norma, day-to-day code.
>>
>>
>> *Motivation 1: std::function constructor*In the same time when return=20
>> type deduction was introduced, std::function<R(Args...)> interface was=
=20
>> extended so this object can be only constructed from the function object=
=20
>> that is callable with Args.. and return type converible to R (modulo voi=
d=20
>> case). That means that the std::function<int(int)> can be constructed fr=
om=20
>> int(*)(int), but not from std::string(*)(std::string).
>> That leads us to ability to write overloaded functions that will accept=
=20
>> std::function object with different signatures:
>> void foo(std::function<int(int)>);
>> void foo(std::function<std::string(std::string)>);
>> For the above overloads, the call=20
>> foo([](int x) { return x + 2; })=20
>> is ambiguous and will select the first overload. But if we will use a=20
>> generic lambda that cannot be invoked with std::string
>> foo([](auto x) { return x + 2; })=20
>> The call will end up with hard compiler error mentoring the no match for=
=20
>> call of operator+ for std::string and int. This error is produced by=20
>> instantiation of the lambda body with string argument that is needed do=
=20
>> determine return type.
>> However if we resign from uses of implicit return type deduction for=20
>> lambda and will explicitly specify it, the code will work again:
>> foo([](auto x) -> decltype(x+2) { return x + 2; });
>> Life example: http://melpon.org/wandbox/permlink/7bunImaydJ8SqyH6
>>
>>
>> *Motivation 2: writing an library code*Lets imagine that we want to=20
>> write an equivalent of not_fn(f) function that returns complement of=20
>> predicate not_fn(f)(args...) is equivalent to f(args..). For simplicity =
it=20
>> will support only const overload operator() and function objects (not=20
>> member pointers). Using decltype(auto) it could be implemented as:
>> template<typename F>
>> struct not_fn_f
>> {
>> not_fn_f(F const& f) : f_(f) {}
>> not_fn_f(F&& f) : f_(std::move(f)) {}
>>
>> template<typename... Args>
>> decltype(auto) operator()(Args&&... args)
>> { return f_(std::forward<Args>(args)...); }
>> =20
>> private:
>> F f_;
>> };
>>
>> template<typename F>
>> not_fn_f<std::decay_t<F>> not_fn(F&& f)
>> {
>> return {std::forward<F>(f)};
>> }
>> Lets consider the behavior of the above code for the following functions=
:
>> void foo(std::function<bool(int)>) {}
>> void foo(std::function<bool(std::string)>) {}
>>
>> bool is_even(int x) { return x =3D=3D 2; }
>> The following invocation is clearly ambiguous and calls first overload.=
=20
>> foo(&is_even);
>> But if the user will want to use not_fn to create an odd functor:
>> foo(not_fn(&is_even));
>> Will produce hard error from instantiation of the not_fn::operator() wit=
h=20
>> std::string. (Life example:=20
>> http://melpon.org/wandbox/permlink/TSVelWZOEMGFtoxT).
>> This problem is again caused by use of return type deduction and will no=
t=20
>> be present if operator() will be declared using decltype(expr): (Life=20
>> example: http://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz)
>> template<typename... Args>
>> auto operator()(Args&&... args) const ->=20
>> decltype(!f_(std::forward<Args>(args)...))
>>
>> To emphasis importance of the problem with lack of SFINAE on return type=
=20
>> deduction, would like to mentoin that above is present for not_fn from G=
CC=20
>> v5.0: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998
>>
>>
>> *Motivation 3: Concepts*There is ongoing work (TS) to introde of the=20
>> Concepts into C++ language. One of the main features is that they will=
=20
>> improve a lot error messages produced by the compiler. For example for=
=20
>> following code:
>> template<typename F, typename... Args>
>> concept bool Predicate =3D requires(F f, Args... args)
>> { {std::forward<F>(f)(std::forward<Args>(args)...)} -> bool };
>>
>> template<typename F, typename T>
>> requires Predicate<F&, T const&>
>> bool apply(F f, T const& t)
>> {
>> return f(t);
>> }
>> The invocation will the form:
>> apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
>> Will produce and short and readable error:
>>
>> prog.cc: In function 'int main()':
>> prog.cc:18:57: error: cannot call function 'bool apply(F, const T&) [wit=
h F =3D main()::<lambda(int)>; T =3D std::__cxx11::basic_string<char>]'
>> apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
>> ^
>> prog.cc:10:6: note: constraints not satisfied
>> bool apply(F f, T const& t)
>> ^
>> prog.cc:10:6: note: concept 'Predicate<main()::<lambda(int)>&, const s=
td::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char=
> >&>' was not satisfied
>> However if we will use generic lambda instead, without return type:
>> apply([](auto x) { return x =3D=3D 2; }, std::string("ala"));
>> The long error will be produced regarding string being not comparable wi=
th int. This error is produced from instantiation of lambda during check of=
the Predicate concept, that requires to see if it is convertible to bool.
>> But again if we reintroduce SFINAE by using decltype(expr) we will again=
get the short and concise error:
>> apply([](auto x) -> decltype(x =3D=3D 2) { return x =3D=3D 2; }, std::st=
ring("ala"));
>> Life example: http://melpon.org/wandbox/permlink/7bqCglI1PAqMLxIW
>>
>>
>> *Summary:*I think that above examples shows that currently return type d=
eduction is not only fulfilling its goal to help library writers, but it is=
also harmful for the language, as is leads to unreadable errors occuring f=
or use of lambda is normal programs, that interface with STL component. I =
believe that all above problem could be changed by requiring that errors pr=
oduced during instantiation requires to create and signature would lead to=
substitution failure instead of ill-formed programs.
>>
>>
>> *Implementability:*The main concern with above change is question if thi=
s is implementable, even for compilers that support expression SFINAE.=20
>>
>> However I would like to point out, that user can reproduced such functio=
nality currently, by doing a transformation of function body:
>> 1. List every expression used in the function body in coma separated lis=
t to void_t<decltype(expr1), decltype(expr2), ...>.=20
>> 2. Every variable declaration in form T x(expr) or T x{expr} transform t=
o T(expr) or T{expr} and add to above list
>> 3. For every declration in form T x =3D initializer; transform it to exp=
ression init<T>(initializer), where init is:
>> template<typename T>
>> void init(T);
>> 4. For every declration in form auto *cv ref* x =3D initializer; transfo=
rm it to expression deduc_auto_*cv_ref*(initializer), where deduc_auto_*cv_=
ref* is:
>> template<typename T>
>> void deduc_auto_*cv_ref*(T *cv ref*);
>> Example:
>> template<typename T>
>> void deduc_auto_const_lref(T const&);
>>
>> So, nearly all functionality (except using declaration) seems to be alre=
ady supported. Futhermore in contrast to function using decltype(expr) or v=
oid_t in they declaration, the above list of expression found in function b=
ody is not required to be mangled into function name, as
>> we do not allow two declaration of the function auto (or other placehold=
er return type).=20
>>
>>
>> *Wording change:*Planned fix change the $7.1.6.4 p12:
>> Return type deduction for a function template with a placeholder in its =
declared type occurs when the
>> definition is instantiated even if the function body contains a return s=
tatement with a non-type-dependent
>> operand. [ Note: Therefore, any use of a specialization of the function =
template will cause an implicit
>> instantiation. Any errors that arise from this instantiation are not in =
the immediate context of the function
>> type and can result in the program being ill-formed. =E2=80=94 end note =
]
>>
>> To:
>> Return type deduction for a function template with a placeholder in its =
declared type occurs when the
>> definition is instantiated even if the function body contains a return s=
tatement with a non-type-dependent
>> operand. [ Note: Therefore, any use of a specialization of the function =
template will cause an implicit
>> instantiation. =E2=80=94 end note ]. Any errors that arise from this ins=
tantiation shall be treated as occurring
>> in the immediate context of the function type.
>>
>> --=20
>>
>> ---=20
>> You received this message because you are subscribed to the Google Group=
s=20
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send a=
n=20
>> email to std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> Visit this group at=20
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
>
--=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_1150_901411322.1446641115326
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">W dniu =C5=9Broda, 4 listopada 2015 13:30:34 UTC+1 u=C5=BC=
ytkownik Mathias Gaunard napisa=C5=82:<blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr">While that would indeed be practical (I currently =
tend to use macros to avoid the repetition required), I think there is also=
value is having a function where the return type is automatically deduced =
while the body is *not* part of the declaration and SFINAE context.<div><br=
></div><div>Making it part of the declaration is also a breaking change whi=
ch is undesirable.</div></div></blockquote><div><br>I fail to see how requi=
ring that failure in instantiation required=20
to deduce a return type an substitution failure will be breaking change.
Now for every declared function template that uses return type=20
deduction, there are two possible output:<br>1. For every set of arguments =
substituted in program, instantiation does not fail and whole program is va=
lid. In this case, proposed change will essentially do nothing, as there ar=
e now failures in instantiation.<br>2. For at least one set of arguments, s=
ubstitution fails. The program is ill-formed according <span style=3D"font-=
family:arial,sans-serif">$7.1.6.4 p12, so change is not breaking (you canno=
t break invalid programs).<br>Also given above possible outputs, I do not s=
ee any value in producing hard error from function instantiation in valid p=
rograms.<br><br>Furthermore my proposition, requires that instantiation err=
ors should be threated as occurring in context in immediate context of func=
tion type, but does include function body as part of declaration (see comme=
nt about mangling in implementation section).<br><br></span></div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><div>I =
therefore suggest you introduce a different syntax for this.</div></div></b=
lockquote><div>Will not help lambda, unless we change rules for lambda defa=
ult return type deduction.<br>=C2=A0</div><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"><div><br><div class=3D"gmail_quote">On Tue, No=
v 3, 2015 at 9:42 PM, Tomasz <span dir=3D"ltr"><<a href=3D"javascript:" =
target=3D"_blank" gdf-obfuscated-mailto=3D"t7SsCXYEFQAJ" rel=3D"nofollow" o=
nmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"th=
is.href=3D'javascript:';return true;">toma...@gmail.com</a>></sp=
an> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><b>Overview:<=
/b><br>C++14 introduced a new feature that allows the=20
return type to be deduced from function body, via use various form of=20
auto (auto cv ref) and decltype(auto) as the return type. This feature=20
was intended to be useful for the library writers, as it should allow=20
them to avoid repetition of the expression in the decltype(expr) and=20
return, however as in contrast to decltype(expr), decltype(auto) leads=20
to hard error (SFIAE) instead of elimination of overlad (SFINAE) it was=20
rarely useful (see not_fn case). Given the fact that such user may be=20
already experienced, this may be considered as not a big problem - they=20
should avoid using return type deduction in context were SFINAE is=20
needed.<br>However, I have recently realized, that the same rules is=20
used for lambda return type deduction and lack of SFINAE for return type
deduction is not only caused problems for library writers (experienced=20
uses of C++), but every uses of generic lambda in norma, day-to-day=20
code.<br><br><b>Motivation 1: std::function constructor<br></b>In the=20
same time when return type deduction was introduced,=20
std::function<R(Args...)> interface was extended so this object=20
can be only constructed from the function object that is callable with=20
Args.. and return type converible to R (modulo void case). That means=20
that the std::function<int(int)> can be constructed from=20
int(*)(int), but not from std::string(*)(std::string).<br>That leads us to =
ability to write overloaded functions that will accept std::function object=
with different signatures:<br><span style=3D"font-family:courier new,monos=
pace">void foo(std::function<int(int)>);<br>void foo(std::function<=
;std::string(<wbr>std::string)>);</span><br>For the above overloads, the=
call <br><span style=3D"font-family:courier new,monospace">foo([](int x) {=
return x + 2; }) </span><br>is ambiguous and will select the first overloa=
d. But if we will use a generic lambda that cannot be invoked with std::str=
ing<br><span style=3D"font-family:courier new,monospace">foo([](auto x) { r=
eturn x + 2; }) <br><span style=3D"font-family:arial,sans-serif">The
call will end up with hard compiler error mentoring the no match for=20
call of operator+ for std::string and int. This error is produced by=20
instantiation of the lambda body with string argument that is needed do=20
determine return type.<br>However if we resign from uses of implicit=20
return type deduction for lambda and will explicitly specify it, the=20
code will work again:<br><span style=3D"font-family:courier new,monospace">=
foo([](auto x) -> decltype(x+2) { return x + 2; });</span><br>Life examp=
le: <a href=3D"http://melpon.org/wandbox/permlink/7bunImaydJ8SqyH6" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\75http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2F7bunImaydJ8S=
qyH6\46sa\75D\46sntz\0751\46usg\75AFQjCNEb11TWn32O6o980pw1XQWVXislBg';r=
eturn true;" onclick=3D"this.href=3D'http://www.google.com/url?q\75http=
%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2F7bunImaydJ8SqyH6\46sa\75D\46sntz=
\0751\46usg\75AFQjCNEb11TWn32O6o980pw1XQWVXislBg';return true;">http://=
melpon.org/wandbox/<wbr>permlink/7bunImaydJ8SqyH6</a><br><br><b>Motivation =
2: writing an library code<br></b>Lets
imagine that we want to write an equivalent of not_fn(f) function that=20
returns complement of predicate not_fn(f)(args...) is equivalent to=20
f(args..). For simplicity it will support only const overload operator()
and function objects (not member pointers). Using decltype(auto) it=20
could be implemented as:<br><span style=3D"font-family:courier new,monospac=
e">template<typename F><br>struct not_fn_f<br>{<br>=C2=A0 not_fn_f(F =
const& f) : f_(f) {}<br>=C2=A0 not_fn_f(F&& f) : f_(std::move(f=
)) {}<br><br>=C2=A0 template<typename... Args><br>=C2=A0 decltype(aut=
o) operator()(Args&&... args)<br>=C2=A0 { return f_(std::forward<=
;Args>(args)...<wbr>); }<br>=C2=A0=C2=A0=C2=A0 <br>private:<br>=C2=A0 F =
f_;<br>};</span><br><br><span style=3D"font-family:courier new,monospace">t=
emplate<typename F><br>not_fn_f<std::decay_t<F>> not_fn(F=
&& f)<br>{<br>=C2=A0=C2=A0=C2=A0 return {std::forward<F>(f)};=
<br>}</span><br>Lets consider the behavior of the above code for the follow=
ing functions:<br><span style=3D"font-family:courier new,monospace">void fo=
o(std::function<bool(int)>) {}<br>void foo(std::function<bool(std:=
:<wbr>string)>) {}<br><br>bool is_even(int x) { return x =3D=3D 2; }</sp=
an><br>The following invocation is clearly ambiguous and calls first overlo=
ad. <br><span style=3D"font-family:courier new,monospace">foo(&is_even)=
;</span><br>But if the user will want to use not_fn to create an odd functo=
r:</span><br>foo(not_fn(&is_even));<br><span style=3D"font-family:arial=
,sans-serif">Will produce hard error from instantiation of the not_fn::oper=
ator() with std::string. (Life example: </span><a href=3D"http://melpon.org=
/wandbox/permlink/TSVelWZOEMGFtoxT" target=3D"_blank" rel=3D"nofollow" onmo=
usedown=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmelp=
on.org%2Fwandbox%2Fpermlink%2FTSVelWZOEMGFtoxT\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNGLzstVeidzgTaMlkyrAr1fcnfUJw';return true;" onclick=3D"this.href=
=3D'http://www.google.com/url?q\75http%3A%2F%2Fmelpon.org%2Fwandbox%2Fp=
ermlink%2FTSVelWZOEMGFtoxT\46sa\75D\46sntz\0751\46usg\75AFQjCNGLzstVeidzgTa=
MlkyrAr1fcnfUJw';return true;">http://melpon.org/wandbox/<wbr>permlink/=
TSVelWZOEMGFtoxT</a>).<br><span style=3D"font-family:arial,sans-serif">This
problem is again caused by use of return type deduction and will not be
present if operator() will be declared using decltype(expr): (Life
example: <a href=3D"http://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz" t=
arget=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://ww=
w.google.com/url?q\75http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2FwrjJVli=
rRH7HXgxz\46sa\75D\46sntz\0751\46usg\75AFQjCNHL8tdpyOGhcggJrAR5b_Mv3V_ReA&#=
39;;return true;" onclick=3D"this.href=3D'http://www.google.com/url?q\7=
5http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2FwrjJVlirRH7HXgxz\46sa\75D\4=
6sntz\0751\46usg\75AFQjCNHL8tdpyOGhcggJrAR5b_Mv3V_ReA';return true;">ht=
tp://melpon.org/wandbox/<wbr>permlink/wrjJVlirRH7HXgxz</a>)<br></span>templ=
ate<typename... Args><br>auto operator()(Args&&... args) cons=
t -> decltype(!f_(std::forward<<wbr>Args>(args)...))<br><br><font =
face=3D"arial,sans-serif">To
emphasis importance of the problem with lack of SFINAE on return type=20
deduction, would like to mentoin that above is present for not_fn from=20
GCC v5.0: <a href=3D"https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998" =
target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://=
www.google.com/url?q\75https%3A%2F%2Fgcc.gnu.org%2Fbugzilla%2Fshow_bug.cgi%=
3Fid%3D66998\46sa\75D\46sntz\0751\46usg\75AFQjCNGKybuKabZ79zaUw2kV4g3mrTot3=
w';return true;" onclick=3D"this.href=3D'https://www.google.com/url=
?q\75https%3A%2F%2Fgcc.gnu.org%2Fbugzilla%2Fshow_bug.cgi%3Fid%3D66998\46sa\=
75D\46sntz\0751\46usg\75AFQjCNGKybuKabZ79zaUw2kV4g3mrTot3w';return true=
;">https://gcc.gnu.org/bugzilla/<wbr>show_bug.cgi?id=3D66998</a></font><br>=
<br></span><b>Motivation 3: Concepts<br></b>There
is ongoing work (TS) to introde of the Concepts into C++ language. One=20
of the main features is that they will improve a lot error messages=20
produced by the compiler. For example for following code:<b><br></b><span s=
tyle=3D"font-family:courier new,monospace">template<typename F, typename=
.... Args><br>concept bool Predicate =3D requires(F f, Args... args)<br>{=
{std::forward<F>(f)(std::<wbr>forward<Args>(args)...)} -> b=
ool };<br><br>template<typename F, typename T><br>=C2=A0 requires Pre=
dicate<F&, T const&><br>bool apply(F f, T const& t)<br>{<=
br>=C2=A0 return f(t);<br>}</span><b><br></b>The invocation will the form:<=
br><span style=3D"font-family:courier new,monospace">apply([](int x) { retu=
rn x =3D=3D 2; }, std::string("ala"));<br><font face=3D"arial,san=
s-serif">Will produce and short and readable error:<br></font></span><pre>p=
rog.cc: In function 'int main()':
prog.cc:18:57: error: cannot call function 'bool apply(F, const T&)=
[with F =3D main()::<lambda(int)>; T =3D std::__cxx11::basic_string&=
lt;<wbr>char>]'
apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
^
prog.cc:10:6: note: constraints not satisfied
bool apply(F f, T const& t)
^
prog.cc:10:6: note: concept 'Predicate<main()::<lambda(<wbr>int=
)>&, const std::__cxx11::basic_string<<wbr>char, std::char_traits=
<char>, std::allocator<char> >&>' was not satisfi=
ed<br><span style=3D"font-family:arial,sans-serif">However if we will use g=
eneric lambda instead, without return type:<br><span style=3D"font-family:c=
ourier new,monospace">apply([](auto x) { return x =3D=3D 2; }, std::string(=
"ala"));</span><br>The long error will be produced regarding stri=
ng being not comparable with int. This error is produced from instantiation=
of lambda during check of the Predicate concept, that requires to see if i=
t is convertible to bool.<br>But again if we reintroduce SFINAE by using de=
cltype(expr) we will again get the short and concise error:<br><span style=
=3D"font-family:courier new,monospace">apply([](auto x) -> decltype(x =
=3D=3D 2) { return x =3D=3D 2; }, std::string("ala"));</span><br>=
Life example: <a href=3D"http://melpon.org/wandbox/permlink/7bqCglI1PAqMLxI=
W" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http:=
//www.google.com/url?q\75http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2F7bq=
CglI1PAqMLxIW\46sa\75D\46sntz\0751\46usg\75AFQjCNGbo6G9dm4krJqMRAxV_CLVtmpE=
HQ';return true;" onclick=3D"this.href=3D'http://www.google.com/url=
?q\75http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2F7bqCglI1PAqMLxIW\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNGbo6G9dm4krJqMRAxV_CLVtmpEHQ';return true;=
">http://melpon.org/wandbox/<wbr>permlink/7bqCglI1PAqMLxIW</a><br><br><b>Su=
mmary:<br></b>I think that above examples shows that currently return type =
deduction is not only fulfilling its goal to help library writers, but it i=
s also harmful for the language, as is leads to unreadable errors occuring =
for use of lambda is normal programs, that interface with STL component. I=
believe that all above problem could be changed by requiring that errors p=
roduced during instantiation requires to create and signature would lead t=
o substitution failure instead of ill-formed programs.<br><br><b>Implementa=
bility:<br></b>The main concern with above change is question if this is im=
plementable, even for compilers that support expression SFINAE. <br><br>How=
ever I would like to point out, that user can reproduced such functionality=
currently, by doing a transformation of function body:<br>1. List every ex=
pression used in the function body in coma separated list to void_t<decl=
type(expr1), decltype(expr2), ...>. <br>2. Every variable declaration in=
form T x(expr) or T x{expr} transform to T(expr) or T{expr} and add to abo=
ve list<br>3. For every declration in form T x =3D initializer; transform i=
t to expression init<T>(initializer), where init is:<br><span style=
=3D"font-family:courier new,monospace">template<typename T><br>void i=
nit(T);</span><br></span><span style=3D"font-family:arial,sans-serif">4. Fo=
r every declration in form auto <i>cv ref</i> x =3D initializer; transform =
it to expression deduc_auto_<i>cv_ref</i>(initializer)<wbr>, where </span><=
span style=3D"font-family:arial,sans-serif"><span style=3D"font-family:aria=
l,sans-serif">deduc_auto_<i>cv_ref</i></span> is:<br></span><span style=3D"=
font-family:arial,sans-serif"></span><span style=3D"font-family:courier new=
,monospace">template<typename T><br>void deduc_auto_<i>cv_ref</i>(T <=
i>cv ref</i>);<br><font face=3D"arial,sans-serif">Example:<br></font></span=
><span style=3D"font-family:courier new,monospace">template<typename T&g=
t;<br>void deduc_auto_const_lref(T const&);<br><br><span style=3D"font-=
family:arial,sans-serif">So, nearly all functionality (except using declara=
tion) seems to be already supported. Futhermore in contrast to function usi=
ng decltype(expr) or void_t in they declaration, the above list of expressi=
on found in function body is not required to be mangled into function name,=
as<br>we do not allow two declaration of the function auto (or other place=
holder return type).</span> <br><br></span><span style=3D"font-family:arial=
,sans-serif"><b>Wording change:<br></b>Planned fix change the $7.1.6.4 p12:=
<br>Return type deduction for a function template with a placeholder in its=
declared type occurs when the<br>definition is instantiated even if the fu=
nction body contains a return statement with a non-type-dependent<br>operan=
d. [ Note: Therefore, any use of a specialization of the function template =
will cause an implicit<br>instantiation. Any errors that arise from this in=
stantiation are not in the immediate context of the function<br>type and ca=
n result in the program being ill-formed. =E2=80=94 end note ]<br><br>To:<b=
r>Return type deduction for a function template with a placeholder in its d=
eclared type occurs when the<br>definition is instantiated even if the func=
tion body contains a return statement with a non-type-dependent<br>operand.=
[ Note: Therefore, any use of a specialization of the function template wi=
ll cause an implicit<br>instantiation. =E2=80=94 end note ]. Any errors tha=
t arise from this instantiation shall be treated as occurring<br>=C2=A0in t=
he immediate context of the function type.<span><font color=3D"#888888"><b>=
<br></b></font></span></span></pre></div><span><font color=3D"#888888">
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
t7SsCXYEFQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:&=
#39;;return true;" onclick=3D"this.href=3D'javascript:';return true=
;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"t7SsCXYEFQAJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
;javascript:';return true;">std-pr...@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';ret=
urn true;" onclick=3D"this.href=3D'http://groups.google.com/a/isocpp.or=
g/group/std-proposals/';return true;">http://groups.google.com/a/<wbr>i=
socpp.org/group/std-<wbr>proposals/</a>.<br>
</font></span></blockquote></div><br></div></div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1150_901411322.1446641115326--
------=_Part_1149_309039405.1446641115315--
.
Author: Mathias Gaunard <mathias@gaunard.com>
Date: Wed, 4 Nov 2015 14:02:06 +0000
Raw View
--001a11418142a77ab60523b774f0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wed, Nov 4, 2015 at 12:45 PM, Tomasz <tomaszkam@gmail.com> wrote:
> W dniu =C5=9Broda, 4 listopada 2015 13:30:34 UTC+1 u=C5=BCytkownik Mathia=
s Gaunard
> napisa=C5=82:
>>
>> While that would indeed be practical (I currently tend to use macros to
>> avoid the repetition required), I think there is also value is having a
>> function where the return type is automatically deduced while the body i=
s
>> *not* part of the declaration and SFINAE context.
>>
>> Making it part of the declaration is also a breaking change which is
>> undesirable.
>>
>
> I fail to see how requiring that failure in instantiation required to
> deduce a return type an substitution failure will be breaking change.
>
Potential problems, off the top of my head:
- not everything in the body is dependent
- lookup can happen at different times
- substitution happens before the best overload is selected, so you end up
instantiating a declaration that you might not even use because that
overload isn't the best
- instantiating the declaration might require a lot more compilation time
and not even terminate
- some constructs are not allowed in decltype (e.g. lambdas)
- it's part of the symbol mangling and affects the ABI.
I also remember playing with a macro that would be defined to either auto
f() -> decltype(body) or auto auto f() depending on what the compiler
supported (none of the use cases needed SFINAE). Lots of nasty bugs, some
arguably compiler ones.
> I therefore suggest you introduce a different syntax for this.
>>
> Will not help lambda, unless we change rules for lambda default return
> type deduction.
>
The new syntax I'd suggest would be something like
template<class T>
auto f(T t) -> something
{
return body;
}
which works just as well for lambdas,
[](auto t) -> something { return body; }
You just have to find a good keyword combination for "something".
decltype(auto) is already taken unfortunately.
>
>
>>
>> On Tue, Nov 3, 2015 at 9:42 PM, Tomasz <toma...@gmail.com> wrote:
>>
>>> *Overview:*
>>> C++14 introduced a new feature that allows the return type to be deduce=
d
>>> from function body, via use various form of auto (auto cv ref) and
>>> decltype(auto) as the return type. This feature was intended to be usef=
ul
>>> for the library writers, as it should allow them to avoid repetition of=
the
>>> expression in the decltype(expr) and return, however as in contrast to
>>> decltype(expr), decltype(auto) leads to hard error (SFIAE) instead of
>>> elimination of overlad (SFINAE) it was rarely useful (see not_fn case).
>>> Given the fact that such user may be already experienced, this may be
>>> considered as not a big problem - they should avoid using return type
>>> deduction in context were SFINAE is needed.
>>> However, I have recently realized, that the same rules is used for
>>> lambda return type deduction and lack of SFINAE for return type deducti=
on
>>> is not only caused problems for library writers (experienced uses of C+=
+),
>>> but every uses of generic lambda in norma, day-to-day code.
>>>
>>>
>>> *Motivation 1: std::function constructor*In the same time when return
>>> type deduction was introduced, std::function<R(Args...)> interface was
>>> extended so this object can be only constructed from the function objec=
t
>>> that is callable with Args.. and return type converible to R (modulo vo=
id
>>> case). That means that the std::function<int(int)> can be constructed f=
rom
>>> int(*)(int), but not from std::string(*)(std::string).
>>> That leads us to ability to write overloaded functions that will accept
>>> std::function object with different signatures:
>>> void foo(std::function<int(int)>);
>>> void foo(std::function<std::string(std::string)>);
>>> For the above overloads, the call
>>> foo([](int x) { return x + 2; })
>>> is ambiguous and will select the first overload. But if we will use a
>>> generic lambda that cannot be invoked with std::string
>>> foo([](auto x) { return x + 2; })
>>> The call will end up with hard compiler error mentoring the no match fo=
r
>>> call of operator+ for std::string and int. This error is produced by
>>> instantiation of the lambda body with string argument that is needed do
>>> determine return type.
>>> However if we resign from uses of implicit return type deduction for
>>> lambda and will explicitly specify it, the code will work again:
>>> foo([](auto x) -> decltype(x+2) { return x + 2; });
>>> Life example: http://melpon.org/wandbox/permlink/7bunImaydJ8SqyH6
>>>
>>>
>>> *Motivation 2: writing an library code*Lets imagine that we want to
>>> write an equivalent of not_fn(f) function that returns complement of
>>> predicate not_fn(f)(args...) is equivalent to f(args..). For simplicity=
it
>>> will support only const overload operator() and function objects (not
>>> member pointers). Using decltype(auto) it could be implemented as:
>>> template<typename F>
>>> struct not_fn_f
>>> {
>>> not_fn_f(F const& f) : f_(f) {}
>>> not_fn_f(F&& f) : f_(std::move(f)) {}
>>>
>>> template<typename... Args>
>>> decltype(auto) operator()(Args&&... args)
>>> { return f_(std::forward<Args>(args)...); }
>>>
>>> private:
>>> F f_;
>>> };
>>>
>>> template<typename F>
>>> not_fn_f<std::decay_t<F>> not_fn(F&& f)
>>> {
>>> return {std::forward<F>(f)};
>>> }
>>> Lets consider the behavior of the above code for the following function=
s:
>>> void foo(std::function<bool(int)>) {}
>>> void foo(std::function<bool(std::string)>) {}
>>>
>>> bool is_even(int x) { return x =3D=3D 2; }
>>> The following invocation is clearly ambiguous and calls first overload.
>>> foo(&is_even);
>>> But if the user will want to use not_fn to create an odd functor:
>>> foo(not_fn(&is_even));
>>> Will produce hard error from instantiation of the not_fn::operator()
>>> with std::string. (Life example:
>>> http://melpon.org/wandbox/permlink/TSVelWZOEMGFtoxT).
>>> This problem is again caused by use of return type deduction and will
>>> not be present if operator() will be declared using decltype(expr): (Li=
fe
>>> example: http://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz)
>>> template<typename... Args>
>>> auto operator()(Args&&... args) const ->
>>> decltype(!f_(std::forward<Args>(args)...))
>>>
>>> To emphasis importance of the problem with lack of SFINAE on return typ=
e
>>> deduction, would like to mentoin that above is present for not_fn from =
GCC
>>> v5.0: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998
>>>
>>>
>>> *Motivation 3: Concepts*There is ongoing work (TS) to introde of the
>>> Concepts into C++ language. One of the main features is that they will
>>> improve a lot error messages produced by the compiler. For example for
>>> following code:
>>> template<typename F, typename... Args>
>>> concept bool Predicate =3D requires(F f, Args... args)
>>> { {std::forward<F>(f)(std::forward<Args>(args)...)} -> bool };
>>>
>>> template<typename F, typename T>
>>> requires Predicate<F&, T const&>
>>> bool apply(F f, T const& t)
>>> {
>>> return f(t);
>>> }
>>> The invocation will the form:
>>> apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
>>> Will produce and short and readable error:
>>>
>>> prog.cc: In function 'int main()':
>>> prog.cc:18:57: error: cannot call function 'bool apply(F, const T&) [wi=
th F =3D main()::<lambda(int)>; T =3D std::__cxx11::basic_string<char>]'
>>> apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
>>> ^
>>> prog.cc:10:6: note: constraints not satisfied
>>> bool apply(F f, T const& t)
>>> ^
>>> prog.cc:10:6: note: concept 'Predicate<main()::<lambda(int)>&, const =
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<cha=
r> >&>' was not satisfied
>>> However if we will use generic lambda instead, without return type:
>>> apply([](auto x) { return x =3D=3D 2; }, std::string("ala"));
>>> The long error will be produced regarding string being not comparable w=
ith int. This error is produced from instantiation of lambda during check o=
f the Predicate concept, that requires to see if it is convertible to bool.
>>> But again if we reintroduce SFINAE by using decltype(expr) we will agai=
n get the short and concise error:
>>> apply([](auto x) -> decltype(x =3D=3D 2) { return x =3D=3D 2; }, std::s=
tring("ala"));
>>> Life example: http://melpon.org/wandbox/permlink/7bqCglI1PAqMLxIW
>>>
>>>
>>> *Summary:*I think that above examples shows that currently return type =
deduction is not only fulfilling its goal to help library writers, but it i=
s also harmful for the language, as is leads to unreadable errors occuring =
for use of lambda is normal programs, that interface with STL component. I=
believe that all above problem could be changed by requiring that errors p=
roduced during instantiation requires to create and signature would lead t=
o substitution failure instead of ill-formed programs.
>>>
>>>
>>> *Implementability:*The main concern with above change is question if th=
is is implementable, even for compilers that support expression SFINAE.
>>>
>>> However I would like to point out, that user can reproduced such functi=
onality currently, by doing a transformation of function body:
>>> 1. List every expression used in the function body in coma separated li=
st to void_t<decltype(expr1), decltype(expr2), ...>.
>>> 2. Every variable declaration in form T x(expr) or T x{expr} transform =
to T(expr) or T{expr} and add to above list
>>> 3. For every declration in form T x =3D initializer; transform it to ex=
pression init<T>(initializer), where init is:
>>> template<typename T>
>>> void init(T);
>>> 4. For every declration in form auto *cv ref* x =3D initializer; transf=
orm it to expression deduc_auto_*cv_ref*(initializer), where deduc_auto_*cv=
_ref* is:
>>> template<typename T>
>>> void deduc_auto_*cv_ref*(T *cv ref*);
>>> Example:
>>> template<typename T>
>>> void deduc_auto_const_lref(T const&);
>>>
>>> So, nearly all functionality (except using declaration) seems to be alr=
eady supported. Futhermore in contrast to function using decltype(expr) or =
void_t in they declaration, the above list of expression found in function =
body is not required to be mangled into function name, as
>>> we do not allow two declaration of the function auto (or other placehol=
der return type).
>>>
>>>
>>> *Wording change:*Planned fix change the $7.1.6.4 p12:
>>> Return type deduction for a function template with a placeholder in its=
declared type occurs when the
>>> definition is instantiated even if the function body contains a return =
statement with a non-type-dependent
>>> operand. [ Note: Therefore, any use of a specialization of the function=
template will cause an implicit
>>> instantiation. Any errors that arise from this instantiation are not in=
the immediate context of the function
>>> type and can result in the program being ill-formed. =E2=80=94 end note=
]
>>>
>>> To:
>>> Return type deduction for a function template with a placeholder in its=
declared type occurs when the
>>> definition is instantiated even if the function body contains a return =
statement with a non-type-dependent
>>> operand. [ Note: Therefore, any use of a specialization of the function=
template will cause an implicit
>>> instantiation. =E2=80=94 end note ]. Any errors that arise from this in=
stantiation shall be treated as occurring
>>> in the immediate context of the function type.
>>>
>>> --
>>>
>>> ---
>>> 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-proposal...@isocpp.org.
>>> To post to this group, send email to std-pr...@isocpp.org.
>>> Visit this group at
>>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>>
>>
>> --
>
> ---
> 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/.
>
--=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/.
--001a11418142a77ab60523b774f0
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Nov 4, 2015 at 12:45 PM, Tomasz <span dir=3D"ltr"><<a href=3D"mailto=
:tomaszkam@gmail.com" target=3D"_blank">tomaszkam@gmail.com</a>></span> =
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">W dniu =C5=9Br=
oda, 4 listopada 2015 13:30:34 UTC+1 u=C5=BCytkownik Mathias Gaunard napisa=
=C5=82:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;=
border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:=
solid;padding-left:1ex"><div dir=3D"ltr">While that would indeed be practic=
al (I currently tend to use macros to avoid the repetition required), I thi=
nk there is also value is having a function where the return type is automa=
tically deduced while the body is *not* part of the declaration and SFINAE =
context.<div><br></div><div>Making it part of the declaration is also a bre=
aking change which is undesirable.</div></div></blockquote></span><div><br>=
I fail to see how requiring that failure in instantiation required=20
to deduce a return type an substitution failure will be breaking change.</d=
iv></div></blockquote><div><br></div><div>Potential problems, off the top o=
f my head:</div><div>- not everything in the body is dependent<br></div><di=
v>- lookup can happen at different times</div><div>- substitution happens b=
efore the best overload is selected, so you end up instantiating a declarat=
ion that you might not even use because that overload isn't the best</d=
iv><div>- instantiating the declaration might require a lot more compilatio=
n time and not even terminate</div><div>- some constructs are not allowed i=
n decltype (e.g. lambdas)</div><div>- it's part of the symbol mangling =
and affects the ABI.</div><div><br></div><div>I also remember playing with =
a macro that would be defined to either auto f() -> decltype(body) or au=
to auto f() depending on what the compiler supported (none of the use cases=
needed SFINAE). Lots of nasty bugs, some arguably compiler ones.</div><div=
><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"marg=
in:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,20=
4);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span class=
=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>I therefore suggest you introd=
uce a different syntax for this.</div></div></blockquote></span><div>Will n=
ot help lambda, unless we change rules for lambda default return type deduc=
tion.<br></div></div></blockquote><div><br></div><div>The new syntax I'=
d suggest would be something like</div><div><br></div><div>template<clas=
s T></div><div>auto f(T t) -> something</div><div>{</div><div>=C2=A0 =
=C2=A0 return body;</div><div>}</div><div><br></div><div>which works just a=
s well for lambdas,</div><div><br></div><div>[](auto t) -> something { r=
eturn body; }</div><div><br></div><div>You just have to find a good keyword=
combination for "something".</div><div>decltype(auto) is already=
taken unfortunately.</div><div>=C2=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-colo=
r:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"lt=
r"><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0=
px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);borde=
r-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><br><div class=
=3D"gmail_quote"><div><div class=3D"h5">On Tue, Nov 3, 2015 at 9:42 PM, Tom=
asz <span dir=3D"ltr"><<a rel=3D"nofollow">toma...@gmail.com</a>></sp=
an> wrote:<br></div></div><blockquote class=3D"gmail_quote" style=3D"margin=
:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204)=
;border-left-style:solid;padding-left:1ex"><div><div class=3D"h5"><div dir=
=3D"ltr"><b>Overview:</b><br>C++14 introduced a new feature that allows the=
=20
return type to be deduced from function body, via use various form of=20
auto (auto cv ref) and decltype(auto) as the return type. This feature=20
was intended to be useful for the library writers, as it should allow=20
them to avoid repetition of the expression in the decltype(expr) and=20
return, however as in contrast to decltype(expr), decltype(auto) leads=20
to hard error (SFIAE) instead of elimination of overlad (SFINAE) it was=20
rarely useful (see not_fn case). Given the fact that such user may be=20
already experienced, this may be considered as not a big problem - they=20
should avoid using return type deduction in context were SFINAE is=20
needed.<br>However, I have recently realized, that the same rules is=20
used for lambda return type deduction and lack of SFINAE for return type
deduction is not only caused problems for library writers (experienced=20
uses of C++), but every uses of generic lambda in norma, day-to-day=20
code.<br><br><b>Motivation 1: std::function constructor<br></b>In the=20
same time when return type deduction was introduced,=20
std::function<R(Args...)> interface was extended so this object=20
can be only constructed from the function object that is callable with=20
Args.. and return type converible to R (modulo void case). That means=20
that the std::function<int(int)> can be constructed from=20
int(*)(int), but not from std::string(*)(std::string).<br>That leads us to =
ability to write overloaded functions that will accept std::function object=
with different signatures:<br><span style=3D"font-family:'courier new&=
#39;,monospace">void foo(std::function<int(int)>);<br>void foo(std::f=
unction<std::string(std::string)>);</span><br>For the above overloads=
, the call <br><span style=3D"font-family:'courier new',monospace">=
foo([](int x) { return x + 2; }) </span><br>is ambiguous and will select th=
e first overload. But if we will use a generic lambda that cannot be invoke=
d with std::string<br><span style=3D"font-family:'courier new',mono=
space">foo([](auto x) { return x + 2; }) <br><span style=3D"font-family:ari=
al,sans-serif">The
call will end up with hard compiler error mentoring the no match for=20
call of operator+ for std::string and int. This error is produced by=20
instantiation of the lambda body with string argument that is needed do=20
determine return type.<br>However if we resign from uses of implicit=20
return type deduction for lambda and will explicitly specify it, the=20
code will work again:<br><span style=3D"font-family:'courier new',m=
onospace">foo([](auto x) -> decltype(x+2) { return x + 2; });</span><br>=
Life example: <a href=3D"http://melpon.org/wandbox/permlink/7bunImaydJ8SqyH=
6" rel=3D"nofollow" target=3D"_blank">http://melpon.org/wandbox/permlink/7b=
unImaydJ8SqyH6</a><br><br><b>Motivation 2: writing an library code<br></b>L=
ets
imagine that we want to write an equivalent of not_fn(f) function that=20
returns complement of predicate not_fn(f)(args...) is equivalent to=20
f(args..). For simplicity it will support only const overload operator()
and function objects (not member pointers). Using decltype(auto) it=20
could be implemented as:<br><span style=3D"font-family:'courier new'=
;,monospace">template<typename F><br>struct not_fn_f<br>{<br>=C2=A0 n=
ot_fn_f(F const& f) : f_(f) {}<br>=C2=A0 not_fn_f(F&& f) : f_(s=
td::move(f)) {}<br><br>=C2=A0 template<typename... Args><br>=C2=A0 de=
cltype(auto) operator()(Args&&... args)<br>=C2=A0 { return f_(std::=
forward<Args>(args)...); }<br>=C2=A0=C2=A0=C2=A0 <br>private:<br>=C2=
=A0 F f_;<br>};</span><br><br><span style=3D"font-family:'courier new&#=
39;,monospace">template<typename F><br>not_fn_f<std::decay_t<F&=
gt;> not_fn(F&& f)<br>{<br>=C2=A0=C2=A0=C2=A0 return {std::forwa=
rd<F>(f)};<br>}</span><br>Lets consider the behavior of the above cod=
e for the following functions:<br><span style=3D"font-family:'courier n=
ew',monospace">void foo(std::function<bool(int)>) {}<br>void foo(=
std::function<bool(std::string)>) {}<br><br>bool is_even(int x) { ret=
urn x =3D=3D 2; }</span><br>The following invocation is clearly ambiguous a=
nd calls first overload. <br><span style=3D"font-family:'courier new=
9;,monospace">foo(&is_even);</span><br>But if the user will want to use=
not_fn to create an odd functor:</span><br>foo(not_fn(&is_even));<br><=
span style=3D"font-family:arial,sans-serif">Will produce hard error from in=
stantiation of the not_fn::operator() with std::string. (Life example: </sp=
an><a href=3D"http://melpon.org/wandbox/permlink/TSVelWZOEMGFtoxT" rel=3D"n=
ofollow" target=3D"_blank">http://melpon.org/wandbox/permlink/TSVelWZOEMGFt=
oxT</a>).<br><span style=3D"font-family:arial,sans-serif">This
problem is again caused by use of return type deduction and will not be
present if operator() will be declared using decltype(expr): (Life
example: <a href=3D"http://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz" r=
el=3D"nofollow" target=3D"_blank">http://melpon.org/wandbox/permlink/wrjJVl=
irRH7HXgxz</a>)<br></span>template<typename... Args><br>auto operator=
()(Args&&... args) const -> decltype(!f_(std::forward<Args>=
;(args)...))<br><br><font face=3D"arial,sans-serif">To
emphasis importance of the problem with lack of SFINAE on return type=20
deduction, would like to mentoin that above is present for not_fn from=20
GCC v5.0: <a href=3D"https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998" =
rel=3D"nofollow" target=3D"_blank">https://gcc.gnu.org/bugzilla/show_bug.cg=
i?id=3D66998</a></font><br><br></span><b>Motivation 3: Concepts<br></b>Ther=
e
is ongoing work (TS) to introde of the Concepts into C++ language. One=20
of the main features is that they will improve a lot error messages=20
produced by the compiler. For example for following code:<b><br></b><span s=
tyle=3D"font-family:'courier new',monospace">template<typename F=
, typename... Args><br>concept bool Predicate =3D requires(F f, Args... =
args)<br>{ {std::forward<F>(f)(std::forward<Args>(args)...)} -&=
gt; bool };<br><br>template<typename F, typename T><br>=C2=A0 require=
s Predicate<F&, T const&><br>bool apply(F f, T const& t)<=
br>{<br>=C2=A0 return f(t);<br>}</span><b><br></b>The invocation will the f=
orm:<br><span style=3D"font-family:'courier new',monospace">apply([=
](int x) { return x =3D=3D 2; }, std::string("ala"));<br><font fa=
ce=3D"arial,sans-serif">Will produce and short and readable error:<br></fon=
t></span><pre>prog.cc: In function 'int main()':
prog.cc:18:57: error: cannot call function 'bool apply(F, const T&)=
[with F =3D main()::<lambda(int)>; T =3D std::__cxx11::basic_string&=
lt;char>]'
apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
^
prog.cc:10:6: note: constraints not satisfied
bool apply(F f, T const& t)
^
prog.cc:10:6: note: concept 'Predicate<main()::<lambda(int)>=
&, const std::__cxx11::basic_string<char, std::char_traits<char&g=
t;, std::allocator<char> >&>' was not satisfied<br><spa=
n style=3D"font-family:arial,sans-serif">However if we will use generic lam=
bda instead, without return type:<br><span style=3D"font-family:'courie=
r new',monospace">apply([](auto x) { return x =3D=3D 2; }, std::string(=
"ala"));</span><br>The long error will be produced regarding stri=
ng being not comparable with int. This error is produced from instantiation=
of lambda during check of the Predicate concept, that requires to see if i=
t is convertible to bool.<br>But again if we reintroduce SFINAE by using de=
cltype(expr) we will again get the short and concise error:<br><span style=
=3D"font-family:'courier new',monospace">apply([](auto x) -> dec=
ltype(x =3D=3D 2) { return x =3D=3D 2; }, std::string("ala"));</s=
pan><br>Life example: <a href=3D"http://melpon.org/wandbox/permlink/7bqCglI=
1PAqMLxIW" rel=3D"nofollow" target=3D"_blank">http://melpon.org/wandbox/per=
mlink/7bqCglI1PAqMLxIW</a><br><br><b>Summary:<br></b>I think that above exa=
mples shows that currently return type deduction is not only fulfilling its=
goal to help library writers, but it is also harmful for the language, as =
is leads to unreadable errors occuring for use of lambda is normal programs=
, that interface with STL component. I believe that all above problem coul=
d be changed by requiring that errors produced during instantiation requir=
es to create and signature would lead to substitution failure instead of il=
l-formed programs.<br><br><b>Implementability:<br></b>The main concern with=
above change is question if this is implementable, even for compilers that=
support expression SFINAE. <br><br>However I would like to point out, that=
user can reproduced such functionality currently, by doing a transformatio=
n of function body:<br>1. List every expression used in the function body i=
n coma separated list to void_t<decltype(expr1), decltype(expr2), ...>=
;. <br>2. Every variable declaration in form T x(expr) or T x{expr} transfo=
rm to T(expr) or T{expr} and add to above list<br>3. For every declration i=
n form T x =3D initializer; transform it to expression init<T>(initia=
lizer), where init is:<br><span style=3D"font-family:'courier new',=
monospace">template<typename T><br>void init(T);</span><br></span><sp=
an style=3D"font-family:arial,sans-serif">4. For every declration in form a=
uto <i>cv ref</i> x =3D initializer; transform it to expression deduc_auto_=
<i>cv_ref</i>(initializer), where </span><span style=3D"font-family:arial,s=
ans-serif"><span style=3D"font-family:arial,sans-serif">deduc_auto_<i>cv_re=
f</i></span> is:<br></span><span style=3D"font-family:arial,sans-serif"></s=
pan><span style=3D"font-family:'courier new',monospace">template<=
;typename T><br>void deduc_auto_<i>cv_ref</i>(T <i>cv ref</i>);<br><font=
face=3D"arial,sans-serif">Example:<br></font></span><span style=3D"font-fa=
mily:'courier new',monospace">template<typename T><br>void de=
duc_auto_const_lref(T const&);<br><br><span style=3D"font-family:arial,=
sans-serif">So, nearly all functionality (except using declaration) seems t=
o be already supported. Futhermore in contrast to function using decltype(e=
xpr) or void_t in they declaration, the above list of expression found in f=
unction body is not required to be mangled into function name, as<br>we do =
not allow two declaration of the function auto (or other placeholder return=
type).</span> <br><br></span><span style=3D"font-family:arial,sans-serif">=
<b>Wording change:<br></b>Planned fix change the $7.1.6.4 p12:<br>Return ty=
pe deduction for a function template with a placeholder in its declared typ=
e occurs when the<br>definition is instantiated even if the function body c=
ontains a return statement with a non-type-dependent<br>operand. [ Note: Th=
erefore, any use of a specialization of the function template will cause an=
implicit<br>instantiation. Any errors that arise from this instantiation a=
re not in the immediate context of the function<br>type and can result in t=
he program being ill-formed. =E2=80=94 end note ]<br><br>To:<br>Return type=
deduction for a function template with a placeholder in its declared type =
occurs when the<br>definition is instantiated even if the function body con=
tains a return statement with a non-type-dependent<br>operand. [ Note: Ther=
efore, any use of a specialization of the function template will cause an i=
mplicit<br>instantiation. =E2=80=94 end note ]. Any errors that arise from =
this instantiation shall be treated as occurring<br>=C2=A0in the immediate =
context of the function type.<span><font color=3D"#888888"><b><br></b></fon=
t></span></span></pre></div></div></div><span><font color=3D"#888888"><div>=
<div class=3D"h5">
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br></div></div>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a rel=3D"nofollow">std-proposal...@isocpp.org</a>.<br>
To post to this group, send email to <a rel=3D"nofollow">std-pr...@isocpp.o=
rg</a>.<span class=3D""><br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"nofollow" target=3D"_blank">http://groups.google.com=
/a/isocpp.org/group/std-proposals/</a>.<br>
</span></font></span></blockquote></div><br></div></div>
</blockquote></div><div class=3D""><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11418142a77ab60523b774f0--
.
Author: Tomasz <tomaszkam@gmail.com>
Date: Wed, 4 Nov 2015 06:47:09 -0800 (PST)
Raw View
------=_Part_226_461662105.1446648429931
Content-Type: multipart/alternative;
boundary="----=_Part_227_344054323.1446648429935"
------=_Part_227_344054323.1446648429935
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
W dniu =C5=9Broda, 4 listopada 2015 15:02:13 UTC+1 u=C5=BCytkownik Mathias =
Gaunard=20
napisa=C5=82:
>
> On Wed, Nov 4, 2015 at 12:45 PM, Tomasz <toma...@gmail.com <javascript:>>=
=20
> wrote:
>
>> W dniu =C5=9Broda, 4 listopada 2015 13:30:34 UTC+1 u=C5=BCytkownik Mathi=
as Gaunard=20
>> napisa=C5=82:
>>>
>>> While that would indeed be practical (I currently tend to use macros to=
=20
>>> avoid the repetition required), I think there is also value is having a=
=20
>>> function where the return type is automatically deduced while the body =
is=20
>>> *not* part of the declaration and SFINAE context.
>>>
>>> Making it part of the declaration is also a breaking change which is=20
>>> undesirable.
>>>
>>
>> I fail to see how requiring that failure in instantiation required to=20
>> deduce a return type an substitution failure will be breaking change.
>>
>
> Potential problems, off the top of my head:
> - not everything in the body is dependent
> - lookup can happen at different times
> - substitution happens before the best overload is selected, so you end u=
p=20
> instantiating a declaration that you might not even use because that=20
> overload isn't the best
> - instantiating the declaration might require a lot more compilation time=
=20
> and not even terminate
> - some constructs are not allowed in decltype (e.g. lambdas)
> - it's part of the symbol mangling and affects the ABI.
>
> I also remember playing with a macro that would be defined to either auto=
=20
> f() -> decltype(body) or auto auto f() depending on what the compiler=20
> supported (none of the use cases needed SFINAE). Lots of nasty bugs, some=
=20
> arguably compiler ones.
>
Ok, I think we have misunderstanding about the change I am proposing.=20
I am *not* proposing that for the function
template<typename T>
auto f(T x) { return x + 2; }
overload resolution should instantiate function body and deduce return type=
=20
and if that deduction fails eliminate the overload, i.e. behave as=20
template<typename T>
auto f(T x) -> decltype(x + 2) =20
I am saying that if return type needs to be deduced in SFINAE context and=
=20
leads to error during function instantiation in should be considered as=20
substitution failure. As current programs are required to be ill-formed for=
=20
such case, this change is non-breaking. Also as the instantiation is=20
already performed in that place that eliminates a lot of your concern. Also=
=20
this does not allow overload on the function body, for the functions that=
=20
uses return type deduction, so program containing following definitions:
template<typename T> auto f(T t) { return x =3D=3D 2; }
template<typename T> auto f(T t) { return t =3D=3D std::string("2"); }
Is still ill formed. That means no change in name mangling is required.
I believe you mean replacing auto f() -> decltype(body) with=20
decltype(auto) f(), not auto f().
=20
>
> =20
>
>> I therefore suggest you introduce a different syntax for this.
>>>
>> Will not help lambda, unless we change rules for lambda default return=
=20
>> type deduction.
>>
>
> The new syntax I'd suggest would be something like
>
> template<class T>
> auto f(T t) -> something
> {
> return body;
> }
>
> which works just as well for lambdas,
>
> [](auto t) -> something { return body; }
>
> You just have to find a good keyword combination for "something".
> decltype(auto) is already taken unfortunately.
>
My whole point is that lambda default should work correctly with language=
=20
components that rely on SFINAE, so they default rules for return type=20
deduction would need to be changed to -> something from -> auto.
=20
> =20
>
>> =20
>>
>>>
>>> On Tue, Nov 3, 2015 at 9:42 PM, Tomasz <toma...@gmail.com> wrote:
>>>
>>>> *Overview:*
>>>> C++14 introduced a new feature that allows the return type to be=20
>>>> deduced from function body, via use various form of auto (auto cv ref)=
and=20
>>>> decltype(auto) as the return type. This feature was intended to be use=
ful=20
>>>> for the library writers, as it should allow them to avoid repetition o=
f the=20
>>>> expression in the decltype(expr) and return, however as in contrast to=
=20
>>>> decltype(expr), decltype(auto) leads to hard error (SFIAE) instead of=
=20
>>>> elimination of overlad (SFINAE) it was rarely useful (see not_fn case)=
..=20
>>>> Given the fact that such user may be already experienced, this may be=
=20
>>>> considered as not a big problem - they should avoid using return type=
=20
>>>> deduction in context were SFINAE is needed.
>>>> However, I have recently realized, that the same rules is used for=20
>>>> lambda return type deduction and lack of SFINAE for return type deduct=
ion=20
>>>> is not only caused problems for library writers (experienced uses of C=
++),=20
>>>> but every uses of generic lambda in norma, day-to-day code.
>>>>
>>>>
>>>> *Motivation 1: std::function constructor*In the same time when return=
=20
>>>> type deduction was introduced, std::function<R(Args...)> interface was=
=20
>>>> extended so this object can be only constructed from the function obje=
ct=20
>>>> that is callable with Args.. and return type converible to R (modulo v=
oid=20
>>>> case). That means that the std::function<int(int)> can be constructed =
from=20
>>>> int(*)(int), but not from std::string(*)(std::string).
>>>> That leads us to ability to write overloaded functions that will accep=
t=20
>>>> std::function object with different signatures:
>>>> void foo(std::function<int(int)>);
>>>> void foo(std::function<std::string(std::string)>);
>>>> For the above overloads, the call=20
>>>> foo([](int x) { return x + 2; })=20
>>>> is ambiguous and will select the first overload. But if we will use a=
=20
>>>> generic lambda that cannot be invoked with std::string
>>>> foo([](auto x) { return x + 2; })=20
>>>> The call will end up with hard compiler error mentoring the no match=
=20
>>>> for call of operator+ for std::string and int. This error is produced =
by=20
>>>> instantiation of the lambda body with string argument that is needed d=
o=20
>>>> determine return type.
>>>> However if we resign from uses of implicit return type deduction for=
=20
>>>> lambda and will explicitly specify it, the code will work again:
>>>> foo([](auto x) -> decltype(x+2) { return x + 2; });
>>>> Life example: http://melpon.org/wandbox/permlink/7bunImaydJ8SqyH6
>>>>
>>>>
>>>> *Motivation 2: writing an library code*Lets imagine that we want to=20
>>>> write an equivalent of not_fn(f) function that returns complement of=
=20
>>>> predicate not_fn(f)(args...) is equivalent to f(args..). For simplicit=
y it=20
>>>> will support only const overload operator() and function objects (not=
=20
>>>> member pointers). Using decltype(auto) it could be implemented as:
>>>> template<typename F>
>>>> struct not_fn_f
>>>> {
>>>> not_fn_f(F const& f) : f_(f) {}
>>>> not_fn_f(F&& f) : f_(std::move(f)) {}
>>>>
>>>> template<typename... Args>
>>>> decltype(auto) operator()(Args&&... args)
>>>> { return f_(std::forward<Args>(args)...); }
>>>> =20
>>>> private:
>>>> F f_;
>>>> };
>>>>
>>>> template<typename F>
>>>> not_fn_f<std::decay_t<F>> not_fn(F&& f)
>>>> {
>>>> return {std::forward<F>(f)};
>>>> }
>>>> Lets consider the behavior of the above code for the following=20
>>>> functions:
>>>> void foo(std::function<bool(int)>) {}
>>>> void foo(std::function<bool(std::string)>) {}
>>>>
>>>> bool is_even(int x) { return x =3D=3D 2; }
>>>> The following invocation is clearly ambiguous and calls first overload=
..=20
>>>> foo(&is_even);
>>>> But if the user will want to use not_fn to create an odd functor:
>>>> foo(not_fn(&is_even));
>>>> Will produce hard error from instantiation of the not_fn::operator()=
=20
>>>> with std::string. (Life example:=20
>>>> http://melpon.org/wandbox/permlink/TSVelWZOEMGFtoxT).
>>>> This problem is again caused by use of return type deduction and will=
=20
>>>> not be present if operator() will be declared using decltype(expr): (L=
ife=20
>>>> example: http://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz)
>>>> template<typename... Args>
>>>> auto operator()(Args&&... args) const ->=20
>>>> decltype(!f_(std::forward<Args>(args)...))
>>>>
>>>> To emphasis importance of the problem with lack of SFINAE on return=20
>>>> type deduction, would like to mentoin that above is present for not_fn=
from=20
>>>> GCC v5.0: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998
>>>>
>>>>
>>>> *Motivation 3: Concepts*There is ongoing work (TS) to introde of the=
=20
>>>> Concepts into C++ language. One of the main features is that they will=
=20
>>>> improve a lot error messages produced by the compiler. For example for=
=20
>>>> following code:
>>>> template<typename F, typename... Args>
>>>> concept bool Predicate =3D requires(F f, Args... args)
>>>> { {std::forward<F>(f)(std::forward<Args>(args)...)} -> bool };
>>>>
>>>> template<typename F, typename T>
>>>> requires Predicate<F&, T const&>
>>>> bool apply(F f, T const& t)
>>>> {
>>>> return f(t);
>>>> }
>>>> The invocation will the form:
>>>> apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
>>>> Will produce and short and readable error:
>>>>
>>>> prog.cc: In function 'int main()':
>>>> prog.cc:18:57: error: cannot call function 'bool apply(F, const T&) [w=
ith F =3D main()::<lambda(int)>; T =3D std::__cxx11::basic_string<char>]'
>>>> apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
>>>> ^
>>>> prog.cc:10:6: note: constraints not satisfied
>>>> bool apply(F f, T const& t)
>>>> ^
>>>> prog.cc:10:6: note: concept 'Predicate<main()::<lambda(int)>&, const=
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<ch=
ar> >&>' was not satisfied
>>>> However if we will use generic lambda instead, without return type:
>>>> apply([](auto x) { return x =3D=3D 2; }, std::string("ala"));
>>>> The long error will be produced regarding string being not comparable =
with int. This error is produced from instantiation of lambda during check =
of the Predicate concept, that requires to see if it is convertible to bool=
..
>>>> But again if we reintroduce SFINAE by using decltype(expr) we will aga=
in get the short and concise error:
>>>> apply([](auto x) -> decltype(x =3D=3D 2) { return x =3D=3D 2; }, std::=
string("ala"));
>>>> Life example: http://melpon.org/wandbox/permlink/7bqCglI1PAqMLxIW
>>>>
>>>>
>>>> *Summary:*I think that above examples shows that currently return type=
deduction is not only fulfilling its goal to help library writers, but it =
is also harmful for the language, as is leads to unreadable errors occuring=
for use of lambda is normal programs, that interface with STL component. =
I believe that all above problem could be changed by requiring that errors =
produced during instantiation requires to create and signature would lead =
to substitution failure instead of ill-formed programs.
>>>>
>>>>
>>>> *Implementability:*The main concern with above change is question if t=
his is implementable, even for compilers that support expression SFINAE.=20
>>>>
>>>> However I would like to point out, that user can reproduced such funct=
ionality currently, by doing a transformation of function body:
>>>> 1. List every expression used in the function body in coma separated l=
ist to void_t<decltype(expr1), decltype(expr2), ...>.=20
>>>> 2. Every variable declaration in form T x(expr) or T x{expr} transform=
to T(expr) or T{expr} and add to above list
>>>> 3. For every declration in form T x =3D initializer; transform it to e=
xpression init<T>(initializer), where init is:
>>>> template<typename T>
>>>> void init(T);
>>>> 4. For every declration in form auto *cv ref* x =3D initializer; trans=
form it to expression deduc_auto_*cv_ref*(initializer), where deduc_auto_*c=
v_ref* is:
>>>> template<typename T>
>>>> void deduc_auto_*cv_ref*(T *cv ref*);
>>>> Example:
>>>> template<typename T>
>>>> void deduc_auto_const_lref(T const&);
>>>>
>>>> So, nearly all functionality (except using declaration) seems to be al=
ready supported. Futhermore in contrast to function using decltype(expr) or=
void_t in they declaration, the above list of expression found in function=
body is not required to be mangled into function name, as
>>>> we do not allow two declaration of the function auto (or other placeho=
lder return type).=20
>>>>
>>>>
>>>> *Wording change:*Planned fix change the $7.1.6.4 p12:
>>>> Return type deduction for a function template with a placeholder in it=
s declared type occurs when the
>>>> definition is instantiated even if the function body contains a return=
statement with a non-type-dependent
>>>> operand. [ Note: Therefore, any use of a specialization of the functio=
n template will cause an implicit
>>>> instantiation. Any errors that arise from this instantiation are not i=
n the immediate context of the function
>>>> type and can result in the program being ill-formed. =E2=80=94 end not=
e ]
>>>>
>>>> To:
>>>> Return type deduction for a function template with a placeholder in it=
s declared type occurs when the
>>>> definition is instantiated even if the function body contains a return=
statement with a non-type-dependent
>>>> operand. [ Note: Therefore, any use of a specialization of the functio=
n template will cause an implicit
>>>> instantiation. =E2=80=94 end note ]. Any errors that arise from this i=
nstantiation shall be treated as occurring
>>>> in the immediate context of the function type.
>>>>
>>>> --=20
>>>>
>>>> ---=20
>>>> You received this message because you are subscribed to the Google=20
>>>> Groups "ISO C++ Standard - Future Proposals" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send=
=20
>>>> an email to std-proposal...@isocpp.org.
>>>> To post to this group, send email to std-pr...@isocpp.org.
>>>> Visit this group at=20
>>>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>>>
>>>
>>> --=20
>>
>> ---=20
>> You received this message because you are subscribed to the Google Group=
s=20
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send a=
n=20
>> email to std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> Visit this group at=20
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
>
--=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_227_344054323.1446648429935
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>W dniu =C5=9Broda, 4 listopada 2015 15:02:13 UTC+1 u=C5=BCytkownik =
Mathias Gaunard napisa=C5=82:<blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr"><div><div class=3D"gmail_quote">On Wed, Nov 4, 2015 at 12:4=
5 PM, Tomasz <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank=
" gdf-obfuscated-mailto=3D"CIonN3YJFQAJ" rel=3D"nofollow" onmousedown=3D"th=
is.href=3D'javascript:';return true;" onclick=3D"this.href=3D'j=
avascript:';return true;">toma...@gmail.com</a>></span> wrote:<br><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pad=
ding-left:1ex"><div dir=3D"ltr"><span>W dniu =C5=9Broda, 4 listopada 2015 1=
3:30:34 UTC+1 u=C5=BCytkownik Mathias Gaunard napisa=C5=82:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;b=
order-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"=
><div dir=3D"ltr">While that would indeed be practical (I currently tend to=
use macros to avoid the repetition required), I think there is also value =
is having a function where the return type is automatically deduced while t=
he body is *not* part of the declaration and SFINAE context.<div><br></div>=
<div>Making it part of the declaration is also a breaking change which is u=
ndesirable.</div></div></blockquote></span><div><br>I fail to see how requi=
ring that failure in instantiation required=20
to deduce a return type an substitution failure will be breaking change.</d=
iv></div></blockquote><div><br></div><div>Potential problems, off the top o=
f my head:</div><div>- not everything in the body is dependent<br></div><di=
v>- lookup can happen at different times</div><div>- substitution happens b=
efore the best overload is selected, so you end up instantiating a declarat=
ion that you might not even use because that overload isn't the best</d=
iv><div>- instantiating the declaration might require a lot more compilatio=
n time and not even terminate</div><div>- some constructs are not allowed i=
n decltype (e.g. lambdas)</div><div>- it's part of the symbol mangling =
and affects the ABI.</div><div><br></div><div>I also remember playing with =
a macro that would be defined to either auto f() -> decltype(body) or au=
to auto f() depending on what the compiler supported (none of the use cases=
needed SFINAE). Lots of nasty bugs, some arguably compiler ones.</div></di=
v></div></div></blockquote><div>Ok, I think we have misunderstanding about =
the change I am proposing. <br><br>I am *not* proposing that for the functi=
on<br><span style=3D"font-family: courier new,monospace;">template<typen=
ame T><br>auto f(T x) { return x + 2; }</span><br>overload resolution sh=
ould instantiate function body and deduce return type and if that deduction=
fails eliminate the overload, i.e. behave as <br><span style=3D"font-famil=
y: courier new,monospace;">template<typename T><br>auto f(T x) -> =
decltype(x + 2)=C2=A0 </span><br><br>I am saying that if return type needs =
to be deduced in SFINAE context and leads to error during function instanti=
ation in should be considered as substitution failure. As current programs =
are required to be ill-formed for such case, this change is non-breaking. A=
lso as the instantiation is already performed in that place that eliminates=
a lot of your concern. Also this does not allow overload on the function b=
ody, for the functions that uses return type deduction, so program containi=
ng following definitions:<br>template<typename T> auto f(T t) { retur=
n x =3D=3D 2; }<br>template<typename T> auto f(T t) { return t =3D=3D=
std::string("2"); }<br>Is still ill formed. That means no change=
in name mangling is required.<br><br>I believe you mean replacing auto f()=
-> decltype(body)=C2=A0 with decltype(auto) f(), not auto f().<br>=C2=
=A0</div><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"><div=
><div class=3D"gmail_quote"><div><br></div><div>=C2=A0</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex=
"><div dir=3D"ltr"><span><blockquote class=3D"gmail_quote" style=3D"margin:=
0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);=
border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>I therefore=
suggest you introduce a different syntax for this.</div></div></blockquote=
></span><div>Will not help lambda, unless we change rules for lambda defaul=
t return type deduction.<br></div></div></blockquote><div><br></div><div>Th=
e new syntax I'd suggest would be something like</div><div><br></div><d=
iv>template<class T></div><div>auto f(T t) -> something</div><div>=
{</div><div>=C2=A0 =C2=A0 return body;</div><div>}</div><div><br></div><div=
>which works just as well for lambdas,</div><div><br></div><div>[](auto t) =
-> something { return body; }</div><div><br></div><div>You just have to =
find a good keyword combination for "something".</div><div>declty=
pe(auto) is already taken unfortunately.</div></div></div></div></blockquot=
e><div><br>My whole point is that lambda default should work correctly with=
language components that rely on SFINAE, so they default rules for return =
type deduction would need to be changed to -> something from -> auto.=
<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r"><div><div class=3D"gmail_quote"><div>=C2=A0</div><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div d=
ir=3D"ltr"><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"marg=
in:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,20=
4);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><br><div=
class=3D"gmail_quote"><div><div>On Tue, Nov 3, 2015 at 9:42 PM, Tomasz <sp=
an dir=3D"ltr"><<a rel=3D"nofollow">toma...@gmail.com</a>></span> wro=
te:<br></div></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border=
-left-style:solid;padding-left:1ex"><div><div><div dir=3D"ltr"><b>Overview:=
</b><br>C++14 introduced a new feature that allows the=20
return type to be deduced from function body, via use various form of=20
auto (auto cv ref) and decltype(auto) as the return type. This feature=20
was intended to be useful for the library writers, as it should allow=20
them to avoid repetition of the expression in the decltype(expr) and=20
return, however as in contrast to decltype(expr), decltype(auto) leads=20
to hard error (SFIAE) instead of elimination of overlad (SFINAE) it was=20
rarely useful (see not_fn case). Given the fact that such user may be=20
already experienced, this may be considered as not a big problem - they=20
should avoid using return type deduction in context were SFINAE is=20
needed.<br>However, I have recently realized, that the same rules is=20
used for lambda return type deduction and lack of SFINAE for return type
deduction is not only caused problems for library writers (experienced=20
uses of C++), but every uses of generic lambda in norma, day-to-day=20
code.<br><br><b>Motivation 1: std::function constructor<br></b>In the=20
same time when return type deduction was introduced,=20
std::function<R(Args...)> interface was extended so this object=20
can be only constructed from the function object that is callable with=20
Args.. and return type converible to R (modulo void case). That means=20
that the std::function<int(int)> can be constructed from=20
int(*)(int), but not from std::string(*)(std::string).<br>That leads us to =
ability to write overloaded functions that will accept std::function object=
with different signatures:<br><span style=3D"font-family:'courier new&=
#39;,monospace">void foo(std::function<int(int)>);<br>void foo(std::f=
unction<std::string(<wbr>std::string)>);</span><br>For the above over=
loads, the call <br><span style=3D"font-family:'courier new',monosp=
ace">foo([](int x) { return x + 2; }) </span><br>is ambiguous and will sele=
ct the first overload. But if we will use a generic lambda that cannot be i=
nvoked with std::string<br><span style=3D"font-family:'courier new'=
,monospace">foo([](auto x) { return x + 2; }) <br><span style=3D"font-famil=
y:arial,sans-serif">The
call will end up with hard compiler error mentoring the no match for=20
call of operator+ for std::string and int. This error is produced by=20
instantiation of the lambda body with string argument that is needed do=20
determine return type.<br>However if we resign from uses of implicit=20
return type deduction for lambda and will explicitly specify it, the=20
code will work again:<br><span style=3D"font-family:'courier new',m=
onospace">foo([](auto x) -> decltype(x+2) { return x + 2; });</span><br>=
Life example: <a href=3D"http://melpon.org/wandbox/permlink/7bunImaydJ8SqyH=
6" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=3D'http:=
//www.google.com/url?q\75http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2F7bu=
nImaydJ8SqyH6\46sa\75D\46sntz\0751\46usg\75AFQjCNEb11TWn32O6o980pw1XQWVXisl=
Bg';return true;" onclick=3D"this.href=3D'http://www.google.com/url=
?q\75http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2F7bunImaydJ8SqyH6\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEb11TWn32O6o980pw1XQWVXislBg';return true;=
">http://melpon.org/wandbox/<wbr>permlink/7bunImaydJ8SqyH6</a><br><br><b>Mo=
tivation 2: writing an library code<br></b>Lets
imagine that we want to write an equivalent of not_fn(f) function that=20
returns complement of predicate not_fn(f)(args...) is equivalent to=20
f(args..). For simplicity it will support only const overload operator()
and function objects (not member pointers). Using decltype(auto) it=20
could be implemented as:<br><span style=3D"font-family:'courier new'=
;,monospace">template<typename F><br>struct not_fn_f<br>{<br>=C2=A0 n=
ot_fn_f(F const& f) : f_(f) {}<br>=C2=A0 not_fn_f(F&& f) : f_(s=
td::move(f)) {}<br><br>=C2=A0 template<typename... Args><br>=C2=A0 de=
cltype(auto) operator()(Args&&... args)<br>=C2=A0 { return f_(std::=
forward<Args>(args)...<wbr>); }<br>=C2=A0=C2=A0=C2=A0 <br>private:<br=
>=C2=A0 F f_;<br>};</span><br><br><span style=3D"font-family:'courier n=
ew',monospace">template<typename F><br>not_fn_f<std::decay_t&l=
t;F>> not_fn(F&& f)<br>{<br>=C2=A0=C2=A0=C2=A0 return {std::f=
orward<F>(f)};<br>}</span><br>Lets consider the behavior of the above=
code for the following functions:<br><span style=3D"font-family:'couri=
er new',monospace">void foo(std::function<bool(int)>) {}<br>void =
foo(std::function<bool(std::<wbr>string)>) {}<br><br>bool is_even(int=
x) { return x =3D=3D 2; }</span><br>The following invocation is clearly am=
biguous and calls first overload. <br><span style=3D"font-family:'couri=
er new',monospace">foo(&is_even);</span><br>But if the user will wa=
nt to use not_fn to create an odd functor:</span><br>foo(not_fn(&is_eve=
n));<br><span style=3D"font-family:arial,sans-serif">Will produce hard erro=
r from instantiation of the not_fn::operator() with std::string. (Life exam=
ple: </span><a href=3D"http://melpon.org/wandbox/permlink/TSVelWZOEMGFtoxT"=
rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=3D'http://=
www.google.com/url?q\75http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2FTSVel=
WZOEMGFtoxT\46sa\75D\46sntz\0751\46usg\75AFQjCNGLzstVeidzgTaMlkyrAr1fcnfUJw=
';return true;" onclick=3D"this.href=3D'http://www.google.com/url?q=
\75http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2FTSVelWZOEMGFtoxT\46sa\75D=
\46sntz\0751\46usg\75AFQjCNGLzstVeidzgTaMlkyrAr1fcnfUJw';return true;">=
http://melpon.org/wandbox/<wbr>permlink/TSVelWZOEMGFtoxT</a>).<br><span sty=
le=3D"font-family:arial,sans-serif">This
problem is again caused by use of return type deduction and will not be
present if operator() will be declared using decltype(expr): (Life
example: <a href=3D"http://melpon.org/wandbox/permlink/wrjJVlirRH7HXgxz" r=
el=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=3D'http://ww=
w.google.com/url?q\75http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2FwrjJVli=
rRH7HXgxz\46sa\75D\46sntz\0751\46usg\75AFQjCNHL8tdpyOGhcggJrAR5b_Mv3V_ReA&#=
39;;return true;" onclick=3D"this.href=3D'http://www.google.com/url?q\7=
5http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2FwrjJVlirRH7HXgxz\46sa\75D\4=
6sntz\0751\46usg\75AFQjCNHL8tdpyOGhcggJrAR5b_Mv3V_ReA';return true;">ht=
tp://melpon.org/wandbox/<wbr>permlink/wrjJVlirRH7HXgxz</a>)<br></span>templ=
ate<typename... Args><br>auto operator()(Args&&... args) cons=
t -> decltype(!f_(std::forward<<wbr>Args>(args)...))<br><br><font =
face=3D"arial,sans-serif">To
emphasis importance of the problem with lack of SFINAE on return type=20
deduction, would like to mentoin that above is present for not_fn from=20
GCC v5.0: <a href=3D"https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D66998" =
rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=3D'https://=
www.google.com/url?q\75https%3A%2F%2Fgcc.gnu.org%2Fbugzilla%2Fshow_bug.cgi%=
3Fid%3D66998\46sa\75D\46sntz\0751\46usg\75AFQjCNGKybuKabZ79zaUw2kV4g3mrTot3=
w';return true;" onclick=3D"this.href=3D'https://www.google.com/url=
?q\75https%3A%2F%2Fgcc.gnu.org%2Fbugzilla%2Fshow_bug.cgi%3Fid%3D66998\46sa\=
75D\46sntz\0751\46usg\75AFQjCNGKybuKabZ79zaUw2kV4g3mrTot3w';return true=
;">https://gcc.gnu.org/bugzilla/<wbr>show_bug.cgi?id=3D66998</a></font><br>=
<br></span><b>Motivation 3: Concepts<br></b>There
is ongoing work (TS) to introde of the Concepts into C++ language. One=20
of the main features is that they will improve a lot error messages=20
produced by the compiler. For example for following code:<b><br></b><span s=
tyle=3D"font-family:'courier new',monospace">template<typename F=
, typename... Args><br>concept bool Predicate =3D requires(F f, Args... =
args)<br>{ {std::forward<F>(f)(std::<wbr>forward<Args>(args)...=
)} -> bool };<br><br>template<typename F, typename T><br>=C2=A0 re=
quires Predicate<F&, T const&><br>bool apply(F f, T const&=
; t)<br>{<br>=C2=A0 return f(t);<br>}</span><b><br></b>The invocation will =
the form:<br><span style=3D"font-family:'courier new',monospace">ap=
ply([](int x) { return x =3D=3D 2; }, std::string("ala"));<br><fo=
nt face=3D"arial,sans-serif">Will produce and short and readable error:<br>=
</font></span><pre>prog.cc: In function 'int main()':
prog.cc:18:57: error: cannot call function 'bool apply(F, const T&)=
[with F =3D main()::<lambda(int)>; T =3D std::__cxx11::basic_string&=
lt;<wbr>char>]'
apply([](int x) { return x =3D=3D 2; }, std::string("ala"));
^
prog.cc:10:6: note: constraints not satisfied
bool apply(F f, T const& t)
^
prog.cc:10:6: note: concept 'Predicate<main()::<lambda(<wbr>int=
)>&, const std::__cxx11::basic_string<<wbr>char, std::char_traits=
<char>, std::allocator<char> >&>' was not satisfi=
ed<br><span style=3D"font-family:arial,sans-serif">However if we will use g=
eneric lambda instead, without return type:<br><span style=3D"font-family:&=
#39;courier new',monospace">apply([](auto x) { return x =3D=3D 2; }, st=
d::string("ala"));</span><br>The long error will be produced rega=
rding string being not comparable with int. This error is produced from ins=
tantiation of lambda during check of the Predicate concept, that requires t=
o see if it is convertible to bool.<br>But again if we reintroduce SFINAE b=
y using decltype(expr) we will again get the short and concise error:<br><s=
pan style=3D"font-family:'courier new',monospace">apply([](auto x) =
-> decltype(x =3D=3D 2) { return x =3D=3D 2; }, std::string("ala&qu=
ot;));</span><br>Life example: <a href=3D"http://melpon.org/wandbox/permlin=
k/7bqCglI1PAqMLxIW" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmelpon.org%2Fwandbox=
%2Fpermlink%2F7bqCglI1PAqMLxIW\46sa\75D\46sntz\0751\46usg\75AFQjCNGbo6G9dm4=
krJqMRAxV_CLVtmpEHQ';return true;" onclick=3D"this.href=3D'http://w=
ww.google.com/url?q\75http%3A%2F%2Fmelpon.org%2Fwandbox%2Fpermlink%2F7bqCgl=
I1PAqMLxIW\46sa\75D\46sntz\0751\46usg\75AFQjCNGbo6G9dm4krJqMRAxV_CLVtmpEHQ&=
#39;;return true;">http://melpon.org/wandbox/<wbr>permlink/7bqCglI1PAqMLxIW=
</a><br><br><b>Summary:<br></b>I think that above examples shows that curre=
ntly return type deduction is not only fulfilling its goal to help library =
writers, but it is also harmful for the language, as is leads to unreadable=
errors occuring for use of lambda is normal programs, that interface with =
STL component. I believe that all above problem could be changed by requir=
ing that errors produced during instantiation requires to create and signa=
ture would lead to substitution failure instead of ill-formed programs.<br>=
<br><b>Implementability:<br></b>The main concern with above change is quest=
ion if this is implementable, even for compilers that support expression SF=
INAE. <br><br>However I would like to point out, that user can reproduced s=
uch functionality currently, by doing a transformation of function body:<br=
>1. List every expression used in the function body in coma separated list =
to void_t<decltype(expr1), decltype(expr2), ...>. <br>2. Every variab=
le declaration in form T x(expr) or T x{expr} transform to T(expr) or T{exp=
r} and add to above list<br>3. For every declration in form T x =3D initial=
izer; transform it to expression init<T>(initializer), where init is:=
<br><span style=3D"font-family:'courier new',monospace">template<=
;typename T><br>void init(T);</span><br></span><span style=3D"font-famil=
y:arial,sans-serif">4. For every declration in form auto <i>cv ref</i> x =
=3D initializer; transform it to expression deduc_auto_<i>cv_ref</i>(initia=
lizer)<wbr>, where </span><span style=3D"font-family:arial,sans-serif"><spa=
n style=3D"font-family:arial,sans-serif">deduc_auto_<i>cv_ref</i></span> is=
:<br></span><span style=3D"font-family:arial,sans-serif"></span><span style=
=3D"font-family:'courier new',monospace">template<typename T>=
<br>void deduc_auto_<i>cv_ref</i>(T <i>cv ref</i>);<br><font face=3D"arial,=
sans-serif">Example:<br></font></span><span style=3D"font-family:'couri=
er new',monospace">template<typename T><br>void deduc_auto_const_=
lref(T const&);<br><br><span style=3D"font-family:arial,sans-serif">So,=
nearly all functionality (except using declaration) seems to be already su=
pported. Futhermore in contrast to function using decltype(expr) or void_t =
in they declaration, the above list of expression found in function body is=
not required to be mangled into function name, as<br>we do not allow two d=
eclaration of the function auto (or other placeholder return type).</span> =
<br><br></span><span style=3D"font-family:arial,sans-serif"><b>Wording chan=
ge:<br></b>Planned fix change the $7.1.6.4 p12:<br>Return type deduction fo=
r a function template with a placeholder in its declared type occurs when t=
he<br>definition is instantiated even if the function body contains a retur=
n statement with a non-type-dependent<br>operand. [ Note: Therefore, any us=
e of a specialization of the function template will cause an implicit<br>in=
stantiation. Any errors that arise from this instantiation are not in the i=
mmediate context of the function<br>type and can result in the program bein=
g ill-formed. =E2=80=94 end note ]<br><br>To:<br>Return type deduction for =
a function template with a placeholder in its declared type occurs when the=
<br>definition is instantiated even if the function body contains a return =
statement with a non-type-dependent<br>operand. [ Note: Therefore, any use =
of a specialization of the function template will cause an implicit<br>inst=
antiation. =E2=80=94 end note ]. Any errors that arise from this instantiat=
ion shall be treated as occurring<br>=C2=A0in the immediate context of the =
function type.<span><font color=3D"#888888"><b><br></b></font></span></span=
></pre></div></div></div><span><font color=3D"#888888"><div><div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br></div></div>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a rel=3D"nofollow">std-proposal...@isocpp.org</a>.<br>
To post to this group, send email to <a rel=3D"nofollow">std-pr...@isocpp.o=
rg</a>.<span><br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=
=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';ret=
urn true;" onclick=3D"this.href=3D'http://groups.google.com/a/isocpp.or=
g/group/std-proposals/';return true;">http://groups.google.com/a/<wbr>i=
socpp.org/group/std-<wbr>proposals/</a>.<br>
</span></font></span></blockquote></div><br></div></div>
</blockquote></div><div><div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
CIonN3YJFQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:&=
#39;;return true;" onclick=3D"this.href=3D'javascript:';return true=
;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"CIonN3YJFQAJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
;javascript:';return true;">std-pr...@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';ret=
urn true;" onclick=3D"this.href=3D'http://groups.google.com/a/isocpp.or=
g/group/std-proposals/';return true;">http://groups.google.com/a/<wbr>i=
socpp.org/group/std-<wbr>proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>
</blockquote>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_227_344054323.1446648429935--
------=_Part_226_461662105.1446648429931--
.
Author: Tomasz <tomaszkam@gmail.com>
Date: Wed, 4 Nov 2015 07:35:53 -0800 (PST)
Raw View
------=_Part_570_2003480944.1446651353379
Content-Type: multipart/alternative;
boundary="----=_Part_571_2102721056.1446651353379"
------=_Part_571_2102721056.1446651353379
Content-Type: text/plain; charset=UTF-8
Maybe some example. I am proposing change that is making decltype(auto) or
auto usefull is you are writting a template definition that is not intended
to be overloaded, like operator() in my simplified not_fn functor or in
all generic lambdas.
template<typename F>
struct not_fn_f
{
not_fn_f(F const& f) : f_(f) {}
not_fn_f(F&& f) : f_(std::move(f)) {}
template<typename... Args>
decltype(auto) operator()(Args&&... args)
{ return f_(std::forward<Args>(args)...); }
private:
F f_;
};
For such cases there is only one candidate for every invocation
not(f)(args...) with specific argument. In that case the ability to
eliminate candidate based on validity of the function body is not
neccessary nor I am proposing to support it. However some library
components (std::function) and proposed concept language feature are making
they behavior depending on the validity of certain expression and may check
if not_fn(f)(args...) is valid. Currently if decltype(auto) or auto is
used, such checks leads to ill-formed program, but I am proposing that
should check should compiler correctly and report that such call is invalid.
This change will not help in situations when we need to eliminate overload
based on validty of certain expression, for example following overload
wrapper, that will call one of the functors, depending on overload
resolution, will still need to use decltype(auto):
template<typename F1, typename F2>
class overload
{
F1 f1;
F2 f2;
public:
overload(F1 a_f1, F2 a_f2)
: f1(std::move(f1))
, f2(std::move(f2))
{}
template<typename... Args>
auto operator()(Args&&... args)
-> decltype(f1(std::forward<Args>(args)...))
{ return f1(std::forward<Args>(args)...); }
template<typename... Args>
auto operator()(Args&&... args)
-> decltype(f2(std::forward<Args>(args)...))
{ return f2(std::forward<Args>(args)...); } };
};
If decltype(auto) will be used, the call overload(fn1, fn2)(args...) is
allways ambiguous, both currently and with the change I am proposing.
I also realized, that decltype(auto) with proposed change, may be not be
usefull also for not_fn implementation that support both const and
non-const 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_571_2102721056.1446651353379
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Maybe some example. I am proposing change that is making d=
ecltype(auto) or auto usefull is you are writting a template definition tha=
t is not intended to be overloaded, like operator() in=C2=A0 my simplified =
not_fn functor or in all generic lambdas.<br><span style=3D"font-family:cou=
rier new,monospace"><span style=3D"font-family:arial,sans-serif"><span styl=
e=3D"font-family:courier new,monospace">template<typename F><br>struc=
t not_fn_f<br>{<br>=C2=A0 not_fn_f(F const& f) : f_(f) {}<br>=C2=A0 not=
_fn_f(F&& f) : f_(std::move(f)) {}<br><br>=C2=A0 template<typena=
me... Args><br>=C2=A0 decltype(auto) operator()(Args&&... args) =
<br>=C2=A0 { return f_(std::forward<Args>(args)...<wbr>); }<br>=C2=A0=
=C2=A0=C2=A0 <br>private:<br>=C2=A0 F f_;<br>};</span><br>For such cases th=
ere is only one candidate for every invocation not(f)(args...) with specifi=
c argument. In that case the ability to eliminate candidate based on validi=
ty of the function body is not neccessary nor I am proposing to support it.=
However some library components (std::function) and proposed concept langu=
age feature are making they behavior depending on the validity of certain e=
xpression and may check if not_fn(f)(args...) is valid. Currently if declty=
pe(auto) or auto is used, such checks leads to ill-formed program, but I am=
proposing that should check should compiler correctly and report that such=
call is invalid.<br><br>This change will not help in situations when we ne=
ed to eliminate overload based on validty of certain expression, for exampl=
e following overload wrapper, that will call one of the functors, depending=
on overload resolution, will still need to use decltype(auto):<br><span st=
yle=3D"font-family: courier new,monospace;">template<typename F1, typena=
me F2><br>class overload<br>{<br></span></span>=C2=A0 F1 f1;<br>=C2=A0 F=
2 f2;<br><br>public:<br>=C2=A0 overload(F1 a_f1, F2 a_f2)<br>=C2=A0=C2=A0 :=
f1(std::move(f1))<br>=C2=A0=C2=A0 , f2(std::move(f2))<br>=C2=A0 {}<br><br>=
<span style=3D"font-family:arial,sans-serif"><span style=3D"font-family: co=
urier new,monospace;">=C2=A0 template<typename... Args><br>=C2=A0 aut=
o operator()(Args&&... args) <br>=C2=A0=C2=A0=C2=A0 -> decltype(=
f1</span></span></span>(<span style=3D"font-family:courier new,monospace"><=
span style=3D"font-family:arial,sans-serif"><span style=3D"font-family: cou=
rier new,monospace;"><span style=3D"font-family:courier new,monospace"><spa=
n style=3D"font-family:arial,sans-serif"><span style=3D"font-family: courie=
r new,monospace;">std::forward<Args>(args)...</span><wbr><span style=
=3D"font-family: courier new,monospace;">))<br></span></span></span>=C2=A0 =
{ return f1(std::forward<Args>(args)...</span><wbr><span style=3D"fon=
t-family: courier new,monospace;">); }=C2=A0=C2=A0 <br></span></span></span=
><br><span style=3D"font-family:courier new,monospace"><span style=3D"font-=
family:arial,sans-serif"><span style=3D"font-family: courier new,monospace;=
"><span style=3D"font-family:courier new,monospace"><span style=3D"font-fam=
ily:arial,sans-serif"><span style=3D"font-family: courier new,monospace;">=
=C2=A0 template<typename... Args><br>=C2=A0 auto operator()(Args&=
&... args) <br>=C2=A0=C2=A0=C2=A0 -> decltype(f2</span></span></span=
>(<span style=3D"font-family:courier new,monospace"><span style=3D"font-fam=
ily:arial,sans-serif"><span style=3D"font-family: courier new,monospace;"><=
span style=3D"font-family:courier new,monospace"><span style=3D"font-family=
:arial,sans-serif"><span style=3D"font-family: courier new,monospace;">std:=
:forward<Args>(args)...</span><wbr><span style=3D"font-family: courie=
r new,monospace;">))<br></span></span>=C2=A0 { return f2(std::forward<Ar=
gs>(args)...</span></span><wbr><span style=3D"font-family: courier new,m=
onospace;">); } </span></span>};</span><br>};<br><span style=3D"font-family=
: arial,sans-serif;">If decltype(auto) will be used, the call overload(fn1,=
fn2)(args...) is allways ambiguous, both currently and with the change I a=
m proposing.<br>I also realized, that decltype(auto) with proposed change, =
may be not be usefull also for not_fn implementation that support both cons=
t and non-const overload. <br>=C2=A0</span><br></span></span></span></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_571_2102721056.1446651353379--
------=_Part_570_2003480944.1446651353379--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 4 Nov 2015 07:53:46 -0800 (PST)
Raw View
------=_Part_209_1720886613.1446652426168
Content-Type: multipart/alternative;
boundary="----=_Part_210_268168931.1446652426168"
------=_Part_210_268168931.1446652426168
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:
>
> W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytkownik Nicol =
Bolas=20
> napisa=C5=82:
>
One reason we don't do that, why we explicitly limit SFINAE to=20
>> parameters/return types, is so that we don't get false positives. If it=
=20
>> gets past the signature, then any errors that happen ought to be real,=
=20
>> genuine errors that a user has to face. That is, someone did something=
=20
>> *wrong*.
>>
> And I am requesting and SFINAE for return type for function using return=
=20
> type deduction.
>
That didn't address my point. Just because a function uses return type=20
deduction doesn't mean it can't get false positives.=20
Not everyone's functions that use return type deduction are tiny.
If you give someone a type and they try to default construct it and that=20
>> fails, then either your template function did something wrong or the use=
r=20
>> passed an inappropriate type. Either way, it should hard error out. We=
=20
>> (will) have concepts to check things like that in the future, so having =
a=20
>> hard error is the right thing. The declaration should not simply disappe=
ar.
>>
>
> Have you checked Motivation 3 regarding the concepts. Lack of SFINAE for=
=20
> return type deduction essentially breaks concept for generic lambda uses,=
=20
> And I do not think that users will constrain every lambda they will write=
..=20
>
I don't see the idea behind Motivation 3. It seems like an admission that=
=20
proper use of concepts will effectively solve the problem. Then you just=20
declare that people won't always use them.
My response to that is... tough. If we give people a tool that fixes a=20
problem, and they refuse to use that tool to fix that exact problem, I=20
refuse to care that they still have the problem.
--=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_210_268168931.1446652426168
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div>W dniu =C5=9Broda, 4 listopada 2015=
02:06:58 UTC+1 u=C5=BCytkownik Nicol Bolas napisa=C5=82:<br></div></blockq=
uote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></d=
iv><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">One reason we d=
on't do that, why we explicitly limit SFINAE to parameters/return types=
, is so that we don't get false positives. If it gets past the signatur=
e, then any errors that happen ought to be real, genuine errors that a user=
has to face. That is, someone did something <i>wrong</i>.<br></div></block=
quote><div>And I am requesting and SFINAE for return type for function usin=
g return type deduction.<br></div></div></blockquote><div><br>That didn'=
;t address my point. Just because a function uses return type deduction doe=
sn't mean it can't get false positives. <br><br>Not everyone's =
functions that use return type deduction are tiny.<br></div><div><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr">If you give someone a type and =
they try to default construct it and that fails, then either your template =
function did something wrong or the user passed an inappropriate type. Eith=
er way, it should hard error out. We (will) have concepts to check things l=
ike that in the future, so having a hard error is the right thing. The decl=
aration should not simply disappear.<br></div></blockquote><div><br>Have yo=
u checked Motivation 3 regarding the concepts. Lack of SFINAE for return ty=
pe deduction essentially breaks concept for generic lambda uses, And I do n=
ot think that users will constrain every lambda they will write. <br></div>=
</div></blockquote><div><br>I don't see the idea behind Motivation 3. I=
t seems like an admission that proper use of concepts will effectively solv=
e the problem. Then you just declare that people won't always use them.=
<br><br>My response to that is... tough. If we give people a tool that fixe=
s a problem, and they refuse to use that tool to fix that exact problem, I =
refuse to care that they still have the problem.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_210_268168931.1446652426168--
------=_Part_209_1720886613.1446652426168--
.
Author: Andrew Sutton <asutton@uakron.edu>
Date: Wed, 4 Nov 2015 11:08:11 -0500
Raw View
> - not everything in the body is dependent
> - lookup can happen at different times
Return type deduction requires instantiation, so I don't think that
this would be a problem.
> - substitution happens before the best overload is selected, so you end up
> instantiating a declaration that you might not even use because that
> overload isn't the best
This is a problem. The language guarantees that a function that is not
used is not instantiated. The proposed change would generate lots of
potential uses that end up being not used because overload resolution
selects a different function.
The reason we don't have this today, is that expression SFINAE is done
in an unevaluated context -- function calls in a decltype() are not
used.
Maybe a better path forward would be to lift the operands of return
statements into a magic declaration type. Kind of like this:
auto f() -> decltype(r1, r2, ...) {
return r1;
...
return r2;
...
}
Except that decltype isn't right because it doesn't guarantee that all
return types are the same.
> - instantiating the declaration might require a lot more compilation time
> and not even terminate
I don't see this as being a big problem. I believe that limits on
depth of instantiation and constexpr evaluation would apply here.
> - some constructs are not allowed in decltype (e.g. lambdas)
That's a potential problem.
> - it's part of the symbol mangling and affects the ABI.
That's also a concern.
Andrew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Mathias Gaunard <mathias@gaunard.com>
Date: Wed, 4 Nov 2015 16:19:22 +0000
Raw View
--001a11c345bc901be20523b95f51
Content-Type: text/plain; charset=UTF-8
On Wed, Nov 4, 2015 at 2:47 PM, Tomasz <tomaszkam@gmail.com> wrote:
>
> I am *not* proposing that for the function
> template<typename T>
> auto f(T x) { return x + 2; }
> overload resolution should instantiate function body and deduce return
> type and if that deduction fails eliminate the overload, i.e. behave as
> template<typename T>
> auto f(T x) -> decltype(x + 2)
>
Functions and lambdas should be governed by the same rules when it comes to
this.
--
---
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/.
--001a11c345bc901be20523b95f51
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Nov 4, 2015 at 2:47 PM, Tomasz <span dir=3D"ltr"><<a href=3D"mailto:=
tomaszkam@gmail.com" target=3D"_blank">tomaszkam@gmail.com</a>></span> w=
rote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div><br>I am *not* proposing that =
for the function<br><span style=3D"font-family:courier new,monospace">templ=
ate<typename T><br>auto f(T x) { return x + 2; }</span><br>overload r=
esolution should instantiate function body and deduce return type and if th=
at deduction fails eliminate the overload, i.e. behave as <br><span style=
=3D"font-family:courier new,monospace">template<typename T><br>auto f=
(T x) -> decltype(x + 2)=C2=A0 </span></div></blockquote><div><br></div>=
<div>Functions and lambdas should be governed by the same rules when it com=
es to this.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c345bc901be20523b95f51--
.
Author: Tomasz <tomaszkam@gmail.com>
Date: Wed, 4 Nov 2015 08:20:26 -0800 (PST)
Raw View
------=_Part_585_759694919.1446654026962
Content-Type: multipart/alternative;
boundary="----=_Part_586_38361942.1446654026962"
------=_Part_586_38361942.1446654026962
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
W dniu =C5=9Broda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik Nicol Bo=
las=20
napisa=C5=82:
>
> On Wednesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:
>>
>> W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytkownik Nicol=
Bolas=20
>> napisa=C5=82:
>>
> One reason we don't do that, why we explicitly limit SFINAE to=20
>>> parameters/return types, is so that we don't get false positives. If it=
=20
>>> gets past the signature, then any errors that happen ought to be real,=
=20
>>> genuine errors that a user has to face. That is, someone did something=
=20
>>> *wrong*.
>>>
>> And I am requesting and SFINAE for return type for function using return=
=20
>> type deduction.
>>
>
> That didn't address my point. Just because a function uses return type=20
> deduction doesn't mean it can't get false positives.=20
>
> Not everyone's functions that use return type deduction are tiny.
>
> If you give someone a type and they try to default construct it and that=
=20
>>> fails, then either your template function did something wrong or the us=
er=20
>>> passed an inappropriate type. Either way, it should hard error out. We=
=20
>>> (will) have concepts to check things like that in the future, so having=
a=20
>>> hard error is the right thing. The declaration should not simply disapp=
ear.
>>>
>>
>> Have you checked Motivation 3 regarding the concepts. Lack of SFINAE for=
=20
>> return type deduction essentially breaks concept for generic lambda uses=
,=20
>> And I do not think that users will constrain every lambda they will writ=
e.=20
>>
>
> I don't see the idea behind Motivation 3. It seems like an admission that=
=20
> proper use of concepts will effectively solve the problem. Then you just=
=20
> declare that people won't always use them.
>
> My response to that is... tough. If we give people a tool that fixes a=20
> problem, and they refuse to use that tool to fix that exact problem, I=20
> refuse to care that they still have the problem.
>
Lambda was created as a tool for creating ad-hoc functor for use with STL=
=20
algorithm in local scope, so requiring them to be constrained, will lead to=
=20
an explosion of ad-hoc constrains, that cannot be declared locally, i.e.=20
lead to C++11 design.=20
--=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_586_38361942.1446654026962
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>W dniu =C5=9Broda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik =
Nicol Bolas napisa=C5=82:<blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On We=
dnesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:<blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div>W dniu =C5=9Broda, 4 listopada 2015 02:06:58 =
UTC+1 u=C5=BCytkownik Nicol Bolas napisa=C5=82:<br></div></blockquote><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"><div></div><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">One reason we don't do tha=
t, why we explicitly limit SFINAE to parameters/return types, is so that we=
don't get false positives. If it gets past the signature, then any err=
ors that happen ought to be real, genuine errors that a user has to face. T=
hat is, someone did something <i>wrong</i>.<br></div></blockquote><div>And =
I am requesting and SFINAE for return type for function using return type d=
eduction.<br></div></div></blockquote><div><br>That didn't address my p=
oint. Just because a function uses return type deduction doesn't mean i=
t can't get false positives. <br><br>Not everyone's functions that =
use return type deduction are tiny.<br></div><div><br></div><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"><blockquote class=3D"gmail_quote"=
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr">If you give someone a type and they try to default =
construct it and that fails, then either your template function did somethi=
ng wrong or the user passed an inappropriate type. Either way, it should ha=
rd error out. We (will) have concepts to check things like that in the futu=
re, so having a hard error is the right thing. The declaration should not s=
imply disappear.<br></div></blockquote><div><br>Have you checked Motivation=
3 regarding the concepts. Lack of SFINAE for return type deduction essenti=
ally breaks concept for generic lambda uses, And I do not think that users =
will constrain every lambda they will write. <br></div></div></blockquote><=
div><br>I don't see the idea behind Motivation 3. It seems like an admi=
ssion that proper use of concepts will effectively solve the problem. Then =
you just declare that people won't always use them.<br><br>My response =
to that is... tough. If we give people a tool that fixes a problem, and the=
y refuse to use that tool to fix that exact problem, I refuse to care that =
they still have the problem.<br></div></blockquote><div><br>Lambda was crea=
ted as a tool for creating ad-hoc functor for use with STL algorithm in loc=
al scope, so requiring them to be constrained, will lead to an explosion of=
ad-hoc constrains, that cannot be declared locally, i.e. lead to C++11 des=
ign. <br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_586_38361942.1446654026962--
------=_Part_585_759694919.1446654026962--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 4 Nov 2015 10:39:19 -0800 (PST)
Raw View
------=_Part_33_1787249951.1446662359106
Content-Type: multipart/alternative;
boundary="----=_Part_34_1208816717.1446662359106"
------=_Part_34_1208816717.1446662359106
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, November 4, 2015 at 11:20:27 AM UTC-5, Tomasz wrote:
>
> W dniu =C5=9Broda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik Nicol =
Bolas=20
> napisa=C5=82:
>>
>> On Wednesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:
>>>
>>> W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytkownik Nico=
l Bolas=20
>>> napisa=C5=82:
>>>
>> One reason we don't do that, why we explicitly limit SFINAE to=20
>>>> parameters/return types, is so that we don't get false positives. If i=
t=20
>>>> gets past the signature, then any errors that happen ought to be real,=
=20
>>>> genuine errors that a user has to face. That is, someone did something=
=20
>>>> *wrong*.
>>>>
>>> And I am requesting and SFINAE for return type for function using retur=
n=20
>>> type deduction.
>>>
>>
>> That didn't address my point. Just because a function uses return type=
=20
>> deduction doesn't mean it can't get false positives.=20
>>
>> Not everyone's functions that use return type deduction are tiny.
>>
>> If you give someone a type and they try to default construct it and that=
=20
>>>> fails, then either your template function did something wrong or the u=
ser=20
>>>> passed an inappropriate type. Either way, it should hard error out. We=
=20
>>>> (will) have concepts to check things like that in the future, so havin=
g a=20
>>>> hard error is the right thing. The declaration should not simply disap=
pear.
>>>>
>>>
>>> Have you checked Motivation 3 regarding the concepts. Lack of SFINAE fo=
r=20
>>> return type deduction essentially breaks concept for generic lambda use=
s,=20
>>> And I do not think that users will constrain every lambda they will wri=
te.=20
>>>
>>
>> I don't see the idea behind Motivation 3. It seems like an admission tha=
t=20
>> proper use of concepts will effectively solve the problem. Then you just=
=20
>> declare that people won't always use them.
>>
>> My response to that is... tough. If we give people a tool that fixes a=
=20
>> problem, and they refuse to use that tool to fix that exact problem, I=
=20
>> refuse to care that they still have the problem.
>>
>
> Lambda was created as a tool for creating ad-hoc functor for use with STL=
=20
> algorithm in local scope, so requiring them to be constrained, will lead =
to=20
> an explosion of ad-hoc constrains, that cannot be declared locally, i.e.=
=20
> lead to C++11 design.
>
Here's what I don't understand about this.
You don't want this feature to allow SFINAE overloading. You don't want=20
this feature to make erroneous code less erroneous (code that triggers your=
=20
auto-SFINAE will fail to instantiate something, which is still an error).=
=20
The *only thing* this feature does is change what the error message you get=
=20
is.
That is *exactly* what concepts are for.
Nobody is requiring that lambdas be constrained. But if you want=20
constrained behavior (which is exactly what you want), you use the tool=20
we've provided to do that.
And I don't buy the whole "lead to an explosion of ad-hoc constrains" bit.=
=20
That sort of argument has been made against concepts in general. Why should=
=20
it be false for, for example, the standard library, yet somehow apply to=20
lambdas? Even your example of `[](auto x) {return x + 2;}` would be a=20
simple case of a (very reuseable) concept for being able to add integers to=
=20
the type. And that could be a simple `[](AdddWith<int> x) {return x + 2;}`.
I see no reason to fundamentally change the nature of template=20
instantiation for this. Especially when the concept makes it much more=20
clear what went wrong.
Also, I don't understand why you seem committed to *only* applying=20
automatic SFINAE to functions with automatically deduced return types. I=20
know that your minimalist use case is `[]() {return expression;}` being=20
converted into `[]() -> decltype(expression) {return expression;}`. But=20
your feature is automatic SFINAE; return type deduction is merely an *imple=
mentation=20
detail* of how the compiler might do it. There's no reason the compiler=20
couldn't implicitly stick an `enable_if` in the return type if it's=20
explicitly specified.
--=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_34_1208816717.1446662359106
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, November 4, 2015 at 11:20:27 AM UTC-5, Tomasz wrote:<blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;">W dniu =C5=9Broda, 4 listopada 2015 16:=
53:46 UTC+1 u=C5=BCytkownik Nicol Bolas napisa=C5=82:<blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex">On Wednesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomas=
z wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div>W dniu =C5=9Broda, 4 l=
istopada 2015 02:06:58 UTC+1 u=C5=BCytkownik Nicol Bolas napisa=C5=82:<br><=
/div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<div></div><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">One rea=
son we don't do that, why we explicitly limit SFINAE to parameters/retu=
rn types, is so that we don't get false positives. If it gets past the =
signature, then any errors that happen ought to be real, genuine errors tha=
t a user has to face. That is, someone did something <i>wrong</i>.<br></div=
></blockquote><div>And I am requesting and SFINAE for return type for funct=
ion using return type deduction.<br></div></div></blockquote><div><br>That =
didn't address my point. Just because a function uses return type deduc=
tion doesn't mean it can't get false positives. <br><br>Not everyon=
e's functions that use return type deduction are tiny.<br></div><div><b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
#ccc solid;padding-left:1ex"><div dir=3D"ltr">If you give someone a type a=
nd they try to default construct it and that fails, then either your templa=
te function did something wrong or the user passed an inappropriate type. E=
ither way, it should hard error out. We (will) have concepts to check thing=
s like that in the future, so having a hard error is the right thing. The d=
eclaration should not simply disappear.<br></div></blockquote><div><br>Have=
you checked Motivation 3 regarding the concepts. Lack of SFINAE for return=
type deduction essentially breaks concept for generic lambda uses, And I d=
o not think that users will constrain every lambda they will write. <br></d=
iv></div></blockquote><div><br>I don't see the idea behind Motivation 3=
.. It seems like an admission that proper use of concepts will effectively s=
olve the problem. Then you just declare that people won't always use th=
em.<br><br>My response to that is... tough. If we give people a tool that f=
ixes a problem, and they refuse to use that tool to fix that exact problem,=
I refuse to care that they still have the problem.<br></div></blockquote><=
div><br>Lambda was created as a tool for creating ad-hoc functor for use wi=
th STL algorithm in local scope, so requiring them to be constrained, will =
lead to an explosion of ad-hoc constrains, that cannot be declared locally,=
i.e. lead to C++11 design.<br></div></blockquote><div><br>Here's what =
I don't understand about this.<br><br>You don't want this feature t=
o allow SFINAE overloading. You don't want this feature to make erroneo=
us code less erroneous (code that triggers your auto-SFINAE will fail to in=
stantiate something, which is still an error). The <i>only thing</i> this f=
eature does is change what the error message you get is.<br><br>That is <i>=
exactly</i> what concepts are for.<br><br>Nobody is requiring that lambdas =
be constrained. But if you want constrained behavior (which is exactly what=
you want), you use the tool we've provided to do that.<br><br>And I do=
n't buy the whole "lead to an explosion of ad-hoc constrains"=
bit. That sort of argument has been made against concepts in general. Why =
should it be false for, for example, the standard library, yet somehow appl=
y to lambdas? Even your example of `[](auto x) {return x + 2;}` would be a =
simple case of a (very reuseable) concept for being able to add integers to=
the type. And that could be a simple `[](AdddWith<int> x) {return x =
+ 2;}`.<br><br>I see no reason to fundamentally change the nature of templa=
te instantiation for this. Especially when the concept makes it much more c=
lear what went wrong.<br><br>Also, I don't understand why you seem comm=
itted to <i>only</i> applying automatic SFINAE to functions with automatica=
lly deduced return types. I know that your minimalist use case is `[]() {re=
turn expression;}` being converted into `[]() -> decltype(expression) {r=
eturn expression;}`. But your feature is automatic SFINAE; return type dedu=
ction is merely an <i>implementation detail</i> of how the compiler might d=
o it. There's no reason the compiler couldn't implicitly stick an `=
enable_if` in the return type if it's explicitly specified.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_34_1208816717.1446662359106--
------=_Part_33_1787249951.1446662359106--
.
Author: anna.salwa.05@gmail.com
Date: Wed, 4 Nov 2015 14:33:07 -0800 (PST)
Raw View
------=_Part_289_1624747429.1446676387771
Content-Type: multipart/alternative;
boundary="----=_Part_290_1104430889.1446676387771"
------=_Part_290_1104430889.1446676387771
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, November 4, 2015 at 7:39:19 PM UTC+1, Nicol Bolas wrote:
>
> On Wednesday, November 4, 2015 at 11:20:27 AM UTC-5, Tomasz wrote:
>>
>> W dniu =C5=9Broda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik Nicol=
Bolas=20
>> napisa=C5=82:
>>>
>>> On Wednesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:
>>>>
>>>> W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytkownik Nic=
ol Bolas=20
>>>> napisa=C5=82:
>>>>
>>> One reason we don't do that, why we explicitly limit SFINAE to=20
>>>>> parameters/return types, is so that we don't get false positives. If =
it=20
>>>>> gets past the signature, then any errors that happen ought to be real=
,=20
>>>>> genuine errors that a user has to face. That is, someone did somethin=
g=20
>>>>> *wrong*.
>>>>>
>>>> And I am requesting and SFINAE for return type for function using=20
>>>> return type deduction.
>>>>
>>>
>>> That didn't address my point. Just because a function uses return type=
=20
>>> deduction doesn't mean it can't get false positives.=20
>>>
>>> Not everyone's functions that use return type deduction are tiny.
>>>
>>> If you give someone a type and they try to default construct it and tha=
t=20
>>>>> fails, then either your template function did something wrong or the =
user=20
>>>>> passed an inappropriate type. Either way, it should hard error out. W=
e=20
>>>>> (will) have concepts to check things like that in the future, so havi=
ng a=20
>>>>> hard error is the right thing. The declaration should not simply disa=
ppear.
>>>>>
>>>>
>>>> Have you checked Motivation 3 regarding the concepts. Lack of SFINAE=
=20
>>>> for return type deduction essentially breaks concept for generic lambd=
a=20
>>>> uses, And I do not think that users will constrain every lambda they w=
ill=20
>>>> write.=20
>>>>
>>>
>>> I don't see the idea behind Motivation 3. It seems like an admission=20
>>> that proper use of concepts will effectively solve the problem. Then yo=
u=20
>>> just declare that people won't always use them.
>>>
>>> My response to that is... tough. If we give people a tool that fixes a=
=20
>>> problem, and they refuse to use that tool to fix that exact problem, I=
=20
>>> refuse to care that they still have the problem.
>>>
>>
>> Lambda was created as a tool for creating ad-hoc functor for use with ST=
L=20
>> algorithm in local scope, so requiring them to be constrained, will lead=
to=20
>> an explosion of ad-hoc constrains, that cannot be declared locally, i.e.=
=20
>> lead to C++11 design.
>>
>
> Here's what I don't understand about this.
>
> You don't want this feature to allow SFINAE overloading. You don't want=
=20
> this feature to make erroneous code less erroneous (code that triggers yo=
ur=20
> auto-SFINAE will fail to instantiate something, which is still an error).=
=20
> The *only thing* this feature does is change what the error message you=
=20
> get is.
>
I am not wanting to allow SFINAE overloading on the function body, i.e.,=20
allow following two declarations to be present and unambiguus:
template<typename T>
auto f(T x) { return x =3D=3D 2; }
template<typename T>
auto f(T x) { return x =3D=3D std::string("2"); }
As this is requiring the whole body to be mangled into signature,=20
introduces full instatiation as part of overload resolution and other=20
problems listed in this thread.
However, my proposal is allowing second level of SFINAE overloads, that=20
makes overload depended on validity of other expression. For example=20
std::function<int(int)> from U is viable only if U can be called with int=
=20
and returns an int. To check that, return type of the function needs to be=
=20
determined anyway, and I am requiring that, if this leads to template=20
instantiation, error produced during it, will lead to elimination of=20
overload, instead of hard error.
This will lead to existing C++14 library features to work with generic=20
lambdas (see motivation 1). That changes does not only change error message=
..
=20
--=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_290_1104430889.1446676387771
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Wednesday, November 4, 2015 at 7:39:19 PM UTC+1, Nicol Bolas wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;">On Wednesday, November 4, 2=
015 at 11:20:27 AM UTC-5, Tomasz wrote:<blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex">W dniu =C5=9Broda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik Nico=
l Bolas napisa=C5=82:<blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">On Wednesday, =
November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div>W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=
=C5=BCytkownik Nicol Bolas napisa=C5=82:<br></div></blockquote><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"><div></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr">One reason we don't do that, wh=
y we explicitly limit SFINAE to parameters/return types, is so that we don&=
#39;t get false positives. If it gets past the signature, then any errors t=
hat happen ought to be real, genuine errors that a user has to face. That i=
s, someone did something <i>wrong</i>.<br></div></blockquote><div>And I am =
requesting and SFINAE for return type for function using return type deduct=
ion.<br></div></div></blockquote><div><br>That didn't address my point.=
Just because a function uses return type deduction doesn't mean it can=
't get false positives. <br><br>Not everyone's functions that use r=
eturn type deduction are tiny.<br></div><div><br></div><blockquote class=3D=
"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr"><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">If you give someone a type and they try to default const=
ruct it and that fails, then either your template function did something wr=
ong or the user passed an inappropriate type. Either way, it should hard er=
ror out. We (will) have concepts to check things like that in the future, s=
o having a hard error is the right thing. The declaration should not simply=
disappear.<br></div></blockquote><div><br>Have you checked Motivation 3 re=
garding the concepts. Lack of SFINAE for return type deduction essentially =
breaks concept for generic lambda uses, And I do not think that users will =
constrain every lambda they will write. <br></div></div></blockquote><div><=
br>I don't see the idea behind Motivation 3. It seems like an admission=
that proper use of concepts will effectively solve the problem. Then you j=
ust declare that people won't always use them.<br><br>My response to th=
at is... tough. If we give people a tool that fixes a problem, and they ref=
use to use that tool to fix that exact problem, I refuse to care that they =
still have the problem.<br></div></blockquote><div><br>Lambda was created a=
s a tool for creating ad-hoc functor for use with STL algorithm in local sc=
ope, so requiring them to be constrained, will lead to an explosion of ad-h=
oc constrains, that cannot be declared locally, i.e. lead to C++11 design.<=
br></div></blockquote><div><br>Here's what I don't understand about=
this.<br><br>You don't want this feature to allow SFINAE overloading. =
You don't want this feature to make erroneous code less erroneous (code=
that triggers your auto-SFINAE will fail to instantiate something, which i=
s still an error). The <i>only thing</i> this feature does is change what t=
he error message you get is.<br></div></blockquote><div><br>I am not wantin=
g to allow SFINAE overloading on the function body, i.e., allow following t=
wo declarations to be present and unambiguus:<br>template<typename T>=
<br>auto f(T x) { return x =3D=3D 2; }<br><br>template<typename T><br=
>auto f(T x) { return x =3D=3D std::string("2"); }<br>As this is =
requiring the whole body to be mangled into signature, introduces full inst=
atiation as part of overload resolution and other problems listed in this t=
hread.<br><br>However, my proposal is allowing second level of SFINAE overl=
oads, that makes overload depended on validity of other expression. For exa=
mple std::function<int(int)> from U is viable only if U can be called=
with int and returns an int. To check that, return type of the function ne=
eds to be determined anyway, and I am requiring that, if this leads to temp=
late instantiation, error produced during it, will lead to elimination of o=
verload, instead of hard error.<br><br>This will lead to existing C++14 lib=
rary features to work with generic lambdas (see motivation 1). That changes=
does not only change error message.<br></div><div>=C2=A0</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_290_1104430889.1446676387771--
------=_Part_289_1624747429.1446676387771--
.
Author: Tomasz <tomaszkam@gmail.com>
Date: Wed, 4 Nov 2015 14:47:35 -0800 (PST)
Raw View
------=_Part_135_477587759.1446677255710
Content-Type: multipart/alternative;
boundary="----=_Part_136_213742746.1446677255711"
------=_Part_136_213742746.1446677255711
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, November 4, 2015 at 7:39:19 PM UTC+1, Nicol Bolas wrote:
>
> On Wednesday, November 4, 2015 at 11:20:27 AM UTC-5, Tomasz wrote:
>>
>> W dniu =C5=9Broda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik Nicol=
Bolas=20
>> napisa=C5=82:
>>>
>>> On Wednesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:
>>>>
>>>> W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytkownik Nic=
ol Bolas=20
>>>> napisa=C5=82:
>>>>
>>> One reason we don't do that, why we explicitly limit SFINAE to=20
>>>>> parameters/return types, is so that we don't get false positives. If =
it=20
>>>>> gets past the signature, then any errors that happen ought to be real=
,=20
>>>>> genuine errors that a user has to face. That is, someone did somethin=
g=20
>>>>> *wrong*.
>>>>>
>>>> And I am requesting and SFINAE for return type for function using=20
>>>> return type deduction.
>>>>
>>>
>>> That didn't address my point. Just because a function uses return type=
=20
>>> deduction doesn't mean it can't get false positives.=20
>>>
>>> Not everyone's functions that use return type deduction are tiny.
>>>
>>> If you give someone a type and they try to default construct it and tha=
t=20
>>>>> fails, then either your template function did something wrong or the =
user=20
>>>>> passed an inappropriate type. Either way, it should hard error out. W=
e=20
>>>>> (will) have concepts to check things like that in the future, so havi=
ng a=20
>>>>> hard error is the right thing. The declaration should not simply disa=
ppear.
>>>>>
>>>>
>>>> Have you checked Motivation 3 regarding the concepts. Lack of SFINAE=
=20
>>>> for return type deduction essentially breaks concept for generic lambd=
a=20
>>>> uses, And I do not think that users will constrain every lambda they w=
ill=20
>>>> write.=20
>>>>
>>>
>>> I don't see the idea behind Motivation 3. It seems like an admission=20
>>> that proper use of concepts will effectively solve the problem. Then yo=
u=20
>>> just declare that people won't always use them.
>>>
>>> My response to that is... tough. If we give people a tool that fixes a=
=20
>>> problem, and they refuse to use that tool to fix that exact problem, I=
=20
>>> refuse to care that they still have the problem.
>>>
>>
>> Lambda was created as a tool for creating ad-hoc functor for use with ST=
L=20
>> algorithm in local scope, so requiring them to be constrained, will lead=
to=20
>> an explosion of ad-hoc constrains, that cannot be declared locally, i.e.=
=20
>> lead to C++11 design.
>>
>
> Here's what I don't understand about this.
>
> You don't want this feature to allow SFINAE overloading. You don't want=
=20
> this feature to make erroneous code less erroneous (code that triggers yo=
ur=20
> auto-SFINAE will fail to instantiate something, which is still an error).=
=20
> The *only thing* this feature does is change what the error message you=
=20
> get is.
>
> I am not wanting to allow SFINAE overloading on the function body, i.e.,=
=20
allow following two declarations to be present and unambiguous:
template<typename T>
auto f(T x) { return x =3D=3D 2; }
template<typename T>
auto f(T x) { return x =3D=3D std::string("2"); }
As this is requiring the whole body to be mangled into signature,=20
introduces full instatiation as part of overload resolution and other=20
problems listed in this thread.
However, my proposal is allowing second level of SFINAE overloads, that=20
makes overload depended on validity of other expression. For example=20
template constuctor of std::function<int(int)> from type U is viable only=
=20
if U can be called with int and returns an int. To check that, return type=
=20
of the function needs to be determined anyway, and I am requiring that, if=
=20
this leads to template instantiation, then error produced during it will=20
lead to elimination of overload, instead of hard error.
This will lead to existing C++14 library features to work with generic=20
lambdas (see motivation 1). That changes does not only change error message=
..
--=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_136_213742746.1446677255711
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, November 4, 2015 at 7:39:19 PM UTC+1, Nicol Bolas wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;">On Wednesday, November 4, 2015 at 1=
1:20:27 AM UTC-5, Tomasz wrote:<blockquote class=3D"gmail_quote" style=3D"m=
argin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">W dn=
iu =C5=9Broda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik Nicol Bolas =
napisa=C5=82:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-lef=
t:0.8ex;border-left:1px #ccc solid;padding-left:1ex">On Wednesday, November=
4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:<blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div>W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytko=
wnik Nicol Bolas napisa=C5=82:<br></div></blockquote><blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr">One reason we don't do that, why we explici=
tly limit SFINAE to parameters/return types, is so that we don't get fa=
lse positives. If it gets past the signature, then any errors that happen o=
ught to be real, genuine errors that a user has to face. That is, someone d=
id something <i>wrong</i>.<br></div></blockquote><div>And I am requesting a=
nd SFINAE for return type for function using return type deduction.<br></di=
v></div></blockquote><div><br>That didn't address my point. Just becaus=
e a function uses return type deduction doesn't mean it can't get f=
alse positives. <br><br>Not everyone's functions that use return type d=
eduction are tiny.<br></div><div><br></div><blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><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">If you give someone a type and they try to default construct it an=
d that fails, then either your template function did something wrong or the=
user passed an inappropriate type. Either way, it should hard error out. W=
e (will) have concepts to check things like that in the future, so having a=
hard error is the right thing. The declaration should not simply disappear=
..<br></div></blockquote><div><br>Have you checked Motivation 3 regarding th=
e concepts. Lack of SFINAE for return type deduction essentially breaks con=
cept for generic lambda uses, And I do not think that users will constrain =
every lambda they will write. <br></div></div></blockquote><div><br>I don&#=
39;t see the idea behind Motivation 3. It seems like an admission that prop=
er use of concepts will effectively solve the problem. Then you just declar=
e that people won't always use them.<br><br>My response to that is... t=
ough. If we give people a tool that fixes a problem, and they refuse to use=
that tool to fix that exact problem, I refuse to care that they still have=
the problem.<br></div></blockquote><div><br>Lambda was created as a tool f=
or creating ad-hoc functor for use with STL algorithm in local scope, so re=
quiring them to be constrained, will lead to an explosion of ad-hoc constra=
ins, that cannot be declared locally, i.e. lead to C++11 design.<br></div><=
/blockquote><div><br>Here's what I don't understand about this.<br>=
<br>You don't want this feature to allow SFINAE overloading. You don=
9;t want this feature to make erroneous code less erroneous (code that trig=
gers your auto-SFINAE will fail to instantiate something, which is still an=
error). The <i>only thing</i> this feature does is change what the error m=
essage you get is.<br><br></div></blockquote><div>I am not wanting to allow=
SFINAE overloading on the function body,=20
i.e., allow following two declarations to be present and unambiguous:<br>te=
mplate<typename T><br>auto f(T x) { return x =3D=3D 2; }<br><br>templ=
ate<typename T><br>auto f(T x) { return x =3D=3D std::string("2&=
quot;); }<br>As
this is requiring the whole body to be mangled into signature,=20
introduces full instatiation as part of overload resolution and other=20
problems listed in this thread.<br><br>However, my proposal is allowing=20
second level of SFINAE overloads, that makes overload depended on=20
validity of other expression. For example template constuctor of std::funct=
ion<int(int)>=20
from type U is viable only if U can be called with int and returns an int. =
To
check that, return type of the function needs to be determined anyway,=20
and I am requiring that, if this leads to template instantiation, then erro=
r=20
produced during it will lead to elimination of overload, instead of=20
hard error.<br><br>This will lead to existing C++14 library features to=20
work with generic lambdas (see motivation 1). That changes does not only
change error message.<br><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_136_213742746.1446677255711--
------=_Part_135_477587759.1446677255710--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 4 Nov 2015 15:46:07 -0800 (PST)
Raw View
------=_Part_362_1656685889.1446680767291
Content-Type: multipart/alternative;
boundary="----=_Part_363_132192894.1446680767292"
------=_Part_363_132192894.1446680767292
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, November 4, 2015 at 5:47:35 PM UTC-5, Tomasz wrote:
>
> On Wednesday, November 4, 2015 at 7:39:19 PM UTC+1, Nicol Bolas wrote:
>>
>> On Wednesday, November 4, 2015 at 11:20:27 AM UTC-5, Tomasz wrote:
>>>
>>> W dniu =C5=9Broda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik Nico=
l Bolas=20
>>> napisa=C5=82:
>>>>
>>>> On Wednesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:
>>>>>
>>>>> W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytkownik Ni=
col Bolas=20
>>>>> napisa=C5=82:
>>>>>
>>>> One reason we don't do that, why we explicitly limit SFINAE to=20
>>>>>> parameters/return types, is so that we don't get false positives. If=
it=20
>>>>>> gets past the signature, then any errors that happen ought to be rea=
l,=20
>>>>>> genuine errors that a user has to face. That is, someone did somethi=
ng=20
>>>>>> *wrong*.
>>>>>>
>>>>> And I am requesting and SFINAE for return type for function using=20
>>>>> return type deduction.
>>>>>
>>>>
>>>> That didn't address my point. Just because a function uses return type=
=20
>>>> deduction doesn't mean it can't get false positives.=20
>>>>
>>>> Not everyone's functions that use return type deduction are tiny.
>>>>
>>>> If you give someone a type and they try to default construct it and=20
>>>>>> that fails, then either your template function did something wrong o=
r the=20
>>>>>> user passed an inappropriate type. Either way, it should hard error =
out. We=20
>>>>>> (will) have concepts to check things like that in the future, so hav=
ing a=20
>>>>>> hard error is the right thing. The declaration should not simply dis=
appear.
>>>>>>
>>>>>
>>>>> Have you checked Motivation 3 regarding the concepts. Lack of SFINAE=
=20
>>>>> for return type deduction essentially breaks concept for generic lamb=
da=20
>>>>> uses, And I do not think that users will constrain every lambda they =
will=20
>>>>> write.=20
>>>>>
>>>>
>>>> I don't see the idea behind Motivation 3. It seems like an admission=
=20
>>>> that proper use of concepts will effectively solve the problem. Then y=
ou=20
>>>> just declare that people won't always use them.
>>>>
>>>> My response to that is... tough. If we give people a tool that fixes a=
=20
>>>> problem, and they refuse to use that tool to fix that exact problem, I=
=20
>>>> refuse to care that they still have the problem.
>>>>
>>>
>>> Lambda was created as a tool for creating ad-hoc functor for use with=
=20
>>> STL algorithm in local scope, so requiring them to be constrained, will=
=20
>>> lead to an explosion of ad-hoc constrains, that cannot be declared loca=
lly,=20
>>> i.e. lead to C++11 design.
>>>
>>
>> Here's what I don't understand about this.
>>
>> You don't want this feature to allow SFINAE overloading. You don't want=
=20
>> this feature to make erroneous code less erroneous (code that triggers y=
our=20
>> auto-SFINAE will fail to instantiate something, which is still an error)=
..=20
>> The *only thing* this feature does is change what the error message you=
=20
>> get is.
>>
>> I am not wanting to allow SFINAE overloading on the function body, i.e.,=
=20
> allow following two declarations to be present and unambiguous:
> template<typename T>
> auto f(T x) { return x =3D=3D 2; }
>
> template<typename T>
> auto f(T x) { return x =3D=3D std::string("2"); }
> As this is requiring the whole body to be mangled into signature,=20
> introduces full instatiation as part of overload resolution and other=20
> problems listed in this thread.
>
> However, my proposal is allowing second level of SFINAE overloads, that=
=20
> makes overload depended on validity of other expression. For example=20
> template constuctor of std::function<int(int)> from type U is viable only=
=20
> if U can be called with int and returns an int. To check that, return typ=
e=20
> of the function needs to be determined anyway, and I am requiring that, i=
f=20
> this leads to template instantiation, then error produced during it will=
=20
> lead to elimination of overload, instead of hard error.
>
> This will lead to existing C++14 library features to work with generic=20
> lambdas (see motivation 1). That changes does not only change error messa=
ge.
>
That does change only the error message. Just look at your example of=20
std::function.
If no SFINAE is involved, you get this <http://ideone.com/jHTUVV>:
#include <iostream>
#include <string>
#include <functional>
using namespace std;
=20
int main()
{
// your code goes here
std::function<int(int)> func1 =3D
[](auto x) {return x + 2;};
std::function<std::string(std::string)> func2 =3D
[](auto x) {return x + 2;};
return 0;
}
In that case, the `func2` elicits a compilation error.
If you explicitly use SFINAE <http://ideone.com/VMGTsV>:
#include <iostream>
#include <string>
#include <functional>
using namespace std;
=20
int main()
{
// your code goes here
std::function<int(int)> func1 =3D
[](auto x) -> decltype(x + 2) {return x + 2;};
std::function<std::string(std::string)> func2 =3D
[](auto x) -> decltype(x + 2) {return x + 2;};
return 0;
}
Guess what? You *still get a compiler error.* `func2`'s initialization is=
=20
just as incorrect as before.
The only difference is the quality of the error.
--=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_363_132192894.1446680767292
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, November 4, 2015 at 5:47:35 PM UTC-5, Tomasz wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;">On Wednesday, November 4, 2015 at 7:39:1=
9 PM UTC+1, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">On We=
dnesday, November 4, 2015 at 11:20:27 AM UTC-5, Tomasz wrote:<blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex">W dniu =C5=9Broda, 4 listopada 2015 16:53:46 UTC+=
1 u=C5=BCytkownik Nicol Bolas napisa=C5=82:<blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex">On Wednesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-=
left:1px #ccc solid;padding-left:1ex"><div>W dniu =C5=9Broda, 4 listopada 2=
015 02:06:58 UTC+1 u=C5=BCytkownik Nicol Bolas napisa=C5=82:<br></div></blo=
ckquote><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div=
><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">One reason we don=
't do that, why we explicitly limit SFINAE to parameters/return types, =
is so that we don't get false positives. If it gets past the signature,=
then any errors that happen ought to be real, genuine errors that a user h=
as to face. That is, someone did something <i>wrong</i>.<br></div></blockqu=
ote><div>And I am requesting and SFINAE for return type for function using =
return type deduction.<br></div></div></blockquote><div><br>That didn't=
address my point. Just because a function uses return type deduction doesn=
't mean it can't get false positives. <br><br>Not everyone's fu=
nctions that use return type deduction are tiny.<br></div><div><br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-=
left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D=
"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr">If you give someone a type and they tr=
y to default construct it and that fails, then either your template functio=
n did something wrong or the user passed an inappropriate type. Either way,=
it should hard error out. We (will) have concepts to check things like tha=
t in the future, so having a hard error is the right thing. The declaration=
should not simply disappear.<br></div></blockquote><div><br>Have you check=
ed Motivation 3 regarding the concepts. Lack of SFINAE for return type dedu=
ction essentially breaks concept for generic lambda uses, And I do not thin=
k that users will constrain every lambda they will write. <br></div></div><=
/blockquote><div><br>I don't see the idea behind Motivation 3. It seems=
like an admission that proper use of concepts will effectively solve the p=
roblem. Then you just declare that people won't always use them.<br><br=
>My response to that is... tough. If we give people a tool that fixes a pro=
blem, and they refuse to use that tool to fix that exact problem, I refuse =
to care that they still have the problem.<br></div></blockquote><div><br>La=
mbda was created as a tool for creating ad-hoc functor for use with STL alg=
orithm in local scope, so requiring them to be constrained, will lead to an=
explosion of ad-hoc constrains, that cannot be declared locally, i.e. lead=
to C++11 design.<br></div></blockquote><div><br>Here's what I don'=
t understand about this.<br><br>You don't want this feature to allow SF=
INAE overloading. You don't want this feature to make erroneous code le=
ss erroneous (code that triggers your auto-SFINAE will fail to instantiate =
something, which is still an error). The <i>only thing</i> this feature doe=
s is change what the error message you get is.<br><br></div></blockquote><d=
iv>I am not wanting to allow SFINAE overloading on the function body,=20
i.e., allow following two declarations to be present and unambiguous:<br>te=
mplate<typename T><br>auto f(T x) { return x =3D=3D 2; }<br><br>templ=
ate<typename T><br>auto f(T x) { return x =3D=3D std::string("2&=
quot;); }<br>As
this is requiring the whole body to be mangled into signature,=20
introduces full instatiation as part of overload resolution and other=20
problems listed in this thread.<br><br>However, my proposal is allowing=20
second level of SFINAE overloads, that makes overload depended on=20
validity of other expression. For example template constuctor of std::funct=
ion<int(int)>=20
from type U is viable only if U can be called with int and returns an int. =
To
check that, return type of the function needs to be determined anyway,=20
and I am requiring that, if this leads to template instantiation, then erro=
r=20
produced during it will lead to elimination of overload, instead of=20
hard error.<br><br>This will lead to existing C++14 library features to=20
work with generic lambdas (see motivation 1). That changes does not only
change error message.<br></div></blockquote><div><br>That does change only=
the error message. Just look at your example of std::function.<br><br><a h=
ref=3D"http://ideone.com/jHTUVV">If no SFINAE is involved, you get this</a>=
:<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"su=
bprettyprint"><span style=3D"color: #800;" class=3D"styled-by-prettify">#in=
clude</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #080;" class=3D"styled-by-prettify"><iostream&g=
t;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: #800;" class=3D"styled-by-prettify">#include</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #080;" class=3D"styled-by-prettify"><string></span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span styl=
e=3D"color: #800;" class=3D"styled-by-prettify">#include</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #080;" class=3D"styled-by-prettify"><functional></span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">using</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">namespace</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> std</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<br></span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> main</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </=
span><span style=3D"color: #800;" class=3D"styled-by-prettify">// your code=
goes here</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>=C2=A0 =C2=A0 std</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">function</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
><</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">)></span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> func1 </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">[](</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> x</span><span style=3D"color: #66=
0;" 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: #008;" class=3D"styled-by-pret=
tify">return</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> x </span><span style=3D"color: #660;" class=3D"styled-by-prettify">+</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #066;" class=3D"styled-by-prettify">2</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 =C2=A0 std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">function</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">string</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">string</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">)></span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> func2 </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">[](</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> x</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: #008;" class=3D"=
styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> x </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">+</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #066;" class=3D"styled-by-prettify">2</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">;};</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #066;" class=3D"styled-by-prettify">0</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>In that case, the `f=
unc2` elicits a compilation error.<br><br><a href=3D"http://ideone.com/VMGT=
sV">If you explicitly use SFINAE</a>:<br><br><div class=3D"prettyprint" sty=
le=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187=
); border-style: solid; border-width: 1px; word-wrap: break-word;"><code cl=
ass=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #80=
0;" class=3D"styled-by-prettify">#include</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #080;" class=
=3D"styled-by-prettify"><iostream></span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br></span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">#include</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #080;" class=3D"style=
d-by-prettify"><string></span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span><span style=3D"color: #800;" class=3D"styled-=
by-prettify">#include</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify=
"><functional></span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">using</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">namespace<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0<br></span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> main</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #800;" cl=
ass=3D"styled-by-prettify">// your code goes here</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 std</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">function</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">int</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">int</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">)></span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> func1 </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">[](</span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> x</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">-></span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #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">x </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">+</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettif=
y">2</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 s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> x </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: #066;" class=3D"style=
d-by-prettify">2</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">;};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>=C2=A0 =C2=A0 std</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">function</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
<</span><span style=3D"color: #000;" class=3D"styled-by-prettify">std</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">string</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">string</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)></span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> func2 </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">[](</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> x</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">-></s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">decltype</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">x </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">+</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styl=
ed-by-prettify">2</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> x </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: #066;" cla=
ss=3D"styled-by-prettify">2</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">;};</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prett=
ify">0</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><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></cod=
e></div><br>Guess what? You <i>still get a compiler error.</i> `func2`'=
s initialization is just as incorrect as before.<br><br>The only difference=
is the quality of the error.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_363_132192894.1446680767292--
------=_Part_362_1656685889.1446680767291--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 4 Nov 2015 15:50:22 -0800 (PST)
Raw View
------=_Part_293_471279124.1446681022576
Content-Type: multipart/alternative;
boundary="----=_Part_294_864047818.1446681022576"
------=_Part_294_864047818.1446681022576
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, November 4, 2015 at 6:46:07 PM UTC-5, Nicol Bolas wrote:
>
> On Wednesday, November 4, 2015 at 5:47:35 PM UTC-5, Tomasz wrote:
>>
>> On Wednesday, November 4, 2015 at 7:39:19 PM UTC+1, Nicol Bolas wrote:
>>>
>>> On Wednesday, November 4, 2015 at 11:20:27 AM UTC-5, Tomasz wrote:
>>>>
>>>> W dniu =C5=9Broda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik Nic=
ol Bolas=20
>>>> napisa=C5=82:
>>>>>
>>>>> On Wednesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:
>>>>>>
>>>>>> W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytkownik N=
icol Bolas=20
>>>>>> napisa=C5=82:
>>>>>>
>>>>> One reason we don't do that, why we explicitly limit SFINAE to=20
>>>>>>> parameters/return types, is so that we don't get false positives. I=
f it=20
>>>>>>> gets past the signature, then any errors that happen ought to be re=
al,=20
>>>>>>> genuine errors that a user has to face. That is, someone did someth=
ing=20
>>>>>>> *wrong*.
>>>>>>>
>>>>>> And I am requesting and SFINAE for return type for function using=20
>>>>>> return type deduction.
>>>>>>
>>>>>
>>>>> That didn't address my point. Just because a function uses return typ=
e=20
>>>>> deduction doesn't mean it can't get false positives.=20
>>>>>
>>>>> Not everyone's functions that use return type deduction are tiny.
>>>>>
>>>>> If you give someone a type and they try to default construct it and=
=20
>>>>>>> that fails, then either your template function did something wrong =
or the=20
>>>>>>> user passed an inappropriate type. Either way, it should hard error=
out. We=20
>>>>>>> (will) have concepts to check things like that in the future, so ha=
ving a=20
>>>>>>> hard error is the right thing. The declaration should not simply di=
sappear.
>>>>>>>
>>>>>>
>>>>>> Have you checked Motivation 3 regarding the concepts. Lack of SFINAE=
=20
>>>>>> for return type deduction essentially breaks concept for generic lam=
bda=20
>>>>>> uses, And I do not think that users will constrain every lambda they=
will=20
>>>>>> write.=20
>>>>>>
>>>>>
>>>>> I don't see the idea behind Motivation 3. It seems like an admission=
=20
>>>>> that proper use of concepts will effectively solve the problem. Then =
you=20
>>>>> just declare that people won't always use them.
>>>>>
>>>>> My response to that is... tough. If we give people a tool that fixes =
a=20
>>>>> problem, and they refuse to use that tool to fix that exact problem, =
I=20
>>>>> refuse to care that they still have the problem.
>>>>>
>>>>
>>>> Lambda was created as a tool for creating ad-hoc functor for use with=
=20
>>>> STL algorithm in local scope, so requiring them to be constrained, wil=
l=20
>>>> lead to an explosion of ad-hoc constrains, that cannot be declared loc=
ally,=20
>>>> i.e. lead to C++11 design.
>>>>
>>>
>>> Here's what I don't understand about this.
>>>
>>> You don't want this feature to allow SFINAE overloading. You don't want=
=20
>>> this feature to make erroneous code less erroneous (code that triggers =
your=20
>>> auto-SFINAE will fail to instantiate something, which is still an error=
).=20
>>> The *only thing* this feature does is change what the error message you=
=20
>>> get is.
>>>
>>> I am not wanting to allow SFINAE overloading on the function body, i.e.=
,=20
>> allow following two declarations to be present and unambiguous:
>> template<typename T>
>> auto f(T x) { return x =3D=3D 2; }
>>
>> template<typename T>
>> auto f(T x) { return x =3D=3D std::string("2"); }
>> As this is requiring the whole body to be mangled into signature,=20
>> introduces full instatiation as part of overload resolution and other=20
>> problems listed in this thread.
>>
>> However, my proposal is allowing second level of SFINAE overloads, that=
=20
>> makes overload depended on validity of other expression. For example=20
>> template constuctor of std::function<int(int)> from type U is viable onl=
y=20
>> if U can be called with int and returns an int. To check that, return ty=
pe=20
>> of the function needs to be determined anyway, and I am requiring that, =
if=20
>> this leads to template instantiation, then error produced during it will=
=20
>> lead to elimination of overload, instead of hard error.
>>
>> This will lead to existing C++14 library features to work with generic=
=20
>> lambdas (see motivation 1). That changes does not only change error mess=
age.
>>
>
> That does change only the error message. Just look at your example of=20
> std::function.
>
> If no SFINAE is involved, you get this <http://ideone.com/jHTUVV>:
>
> #include <iostream>
> #include <string>
> #include <functional>
> using namespace std;
> =20
> int main()
> {
> // your code goes here
> std::function<int(int)> func1 =3D
> [](auto x) {return x + 2;};
> std::function<std::string(std::string)> func2 =3D
> [](auto x) {return x + 2;};
> return 0;
> }
>
> In that case, the `func2` elicits a compilation error.
>
> If you explicitly use SFINAE <http://ideone.com/VMGTsV>:
>
> #include <iostream>
> #include <string>
> #include <functional>
> using namespace std;
> =20
> int main()
> {
> // your code goes here
> std::function<int(int)> func1 =3D
> [](auto x) -> decltype(x + 2) {return x + 2;};
> std::function<std::string(std::string)> func2 =3D
> [](auto x) -> decltype(x + 2) {return x + 2;};
> return 0;
> }
>
> Guess what? You *still get a compiler error.* `func2`'s initialization is=
=20
> just as incorrect as before.
>
> The only difference is the quality of the error.
>
And to be honest, I can't even say that the error quality for the SFINAE=20
case is an improvement. Oh sure, there isn't a gigantic error spew. But at=
=20
least the error spew tells you that it's a template instantiation problem.=
=20
With SFINAE, the compiler just points at the line and says that it couldn't=
=20
do it.
With concepts, the error will be obvious: the type you passed does not=20
provide the concept due to the failure to do X.
--=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_294_864047818.1446681022576
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, November 4, 2015 at 6:46:07 PM UTC-5, Nicol Bolas wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;">On Wednesday, November 4, 2015 at 5=
:47:35 PM UTC-5, Tomasz wrote:<blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">On We=
dnesday, November 4, 2015 at 7:39:19 PM UTC+1, Nicol Bolas wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
#ccc solid;padding-left:1ex">On Wednesday, November 4, 2015 at 11:20:27 AM=
UTC-5, Tomasz wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">W dniu =C5=9Br=
oda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik Nicol Bolas napisa=C5=
=82:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex">On Wednesday, November 4, 2015 =
at 1:12:39 AM UTC-5, Tomasz wrote:<blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div>W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytkownik Ni=
col Bolas napisa=C5=82:<br></div></blockquote><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr">One reason we don't do that, why we explicitly lim=
it SFINAE to parameters/return types, is so that we don't get false pos=
itives. If it gets past the signature, then any errors that happen ought to=
be real, genuine errors that a user has to face. That is, someone did some=
thing <i>wrong</i>.<br></div></blockquote><div>And I am requesting and SFIN=
AE for return type for function using return type deduction.<br></div></div=
></blockquote><div><br>That didn't address my point. Just because a fun=
ction uses return type deduction doesn't mean it can't get false po=
sitives. <br><br>Not everyone's functions that use return type deductio=
n are tiny.<br></div><div><br></div><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"><blockquote class=3D"gmail_quote" style=3D"margin:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
If you give someone a type and they try to default construct it and that fa=
ils, then either your template function did something wrong or the user pas=
sed an inappropriate type. Either way, it should hard error out. We (will) =
have concepts to check things like that in the future, so having a hard err=
or is the right thing. The declaration should not simply disappear.<br></di=
v></blockquote><div><br>Have you checked Motivation 3 regarding the concept=
s. Lack of SFINAE for return type deduction essentially breaks concept for =
generic lambda uses, And I do not think that users will constrain every lam=
bda they will write. <br></div></div></blockquote><div><br>I don't see =
the idea behind Motivation 3. It seems like an admission that proper use of=
concepts will effectively solve the problem. Then you just declare that pe=
ople won't always use them.<br><br>My response to that is... tough. If =
we give people a tool that fixes a problem, and they refuse to use that too=
l to fix that exact problem, I refuse to care that they still have the prob=
lem.<br></div></blockquote><div><br>Lambda was created as a tool for creati=
ng ad-hoc functor for use with STL algorithm in local scope, so requiring t=
hem to be constrained, will lead to an explosion of ad-hoc constrains, that=
cannot be declared locally, i.e. lead to C++11 design.<br></div></blockquo=
te><div><br>Here's what I don't understand about this.<br><br>You d=
on't want this feature to allow SFINAE overloading. You don't want =
this feature to make erroneous code less erroneous (code that triggers your=
auto-SFINAE will fail to instantiate something, which is still an error). =
The <i>only thing</i> this feature does is change what the error message yo=
u get is.<br><br></div></blockquote><div>I am not wanting to allow SFINAE o=
verloading on the function body,=20
i.e., allow following two declarations to be present and unambiguous:<br>te=
mplate<typename T><br>auto f(T x) { return x =3D=3D 2; }<br><br>templ=
ate<typename T><br>auto f(T x) { return x =3D=3D std::string("2&=
quot;); }<br>As
this is requiring the whole body to be mangled into signature,=20
introduces full instatiation as part of overload resolution and other=20
problems listed in this thread.<br><br>However, my proposal is allowing=20
second level of SFINAE overloads, that makes overload depended on=20
validity of other expression. For example template constuctor of std::funct=
ion<int(int)>=20
from type U is viable only if U can be called with int and returns an int. =
To
check that, return type of the function needs to be determined anyway,=20
and I am requiring that, if this leads to template instantiation, then erro=
r=20
produced during it will lead to elimination of overload, instead of=20
hard error.<br><br>This will lead to existing C++14 library features to=20
work with generic lambdas (see motivation 1). That changes does not only
change error message.<br></div></blockquote><div><br>That does change only=
the error message. Just look at your example of std::function.<br><br><a h=
ref=3D"http://ideone.com/jHTUVV" target=3D"_blank" rel=3D"nofollow" onmouse=
down=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fideone.=
com%2FjHTUVV\46sa\75D\46sntz\0751\46usg\75AFQjCNErKQ3tjsxaCC2uLK4jE3TyT8itH=
g';return true;" onclick=3D"this.href=3D'http://www.google.com/url?=
q\75http%3A%2F%2Fideone.com%2FjHTUVV\46sa\75D\46sntz\0751\46usg\75AFQjCNErK=
Q3tjsxaCC2uLK4jE3TyT8itHg';return true;">If no SFINAE is involved, you =
get this</a>:<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"><code><div><span style=3D"color:#800">#include</span><span style=3D"=
color:#000"> </span><span style=3D"color:#080"><iostream></span><span=
style=3D"color:#000"><br></span><span style=3D"color:#800">#include</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#080"><string>=
;</span><span style=3D"color:#000"><br></span><span style=3D"color:#800">#i=
nclude</span><span style=3D"color:#000"> </span><span style=3D"color:#080">=
<functional></span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">using</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">namespace</span><span style=3D"color:#000"> std</span><span=
style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0<br></sp=
an><span style=3D"color:#008">int</span><span style=3D"color:#000"> main</s=
pan><span style=3D"color:#660">()</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0=
=C2=A0 </span><span style=3D"color:#800">// your code goes here</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#008">function</span><span style=3D"color:=
#660"><</span><span style=3D"color:#008">int</span><span style=3D"color:=
#660">(</span><span style=3D"color:#008">int</span><span style=3D"color:#66=
0">)></span><span style=3D"color:#000"> func1 </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#660">[](</span><span style=3D"color:#008">=
auto</span><span style=3D"color:#000"> x</span><span style=3D"color:#660">)=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</spa=
n><span style=3D"color:#008">return</span><span style=3D"color:#000"> x </s=
pan><span style=3D"color:#660">+</span><span style=3D"color:#000"> </span><=
span style=3D"color:#066">2</span><span style=3D"color:#660">;};</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#008">function</span><span style=3D"color:=
#660"><</span><span style=3D"color:#000">std</span><span style=3D"color:=
#660">::</span><span style=3D"color:#008">string</span><span style=3D"color=
:#660">(</span><span style=3D"color:#000">std</span><span style=3D"color:#6=
60">:<wbr>:</span><span style=3D"color:#008">string</span><span style=3D"co=
lor:#660">)></span><span style=3D"color:#000"> func2 </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#660">[](</span><span style=3D"color=
:#008">auto</span><span style=3D"color:#000"> x</span><span style=3D"color:=
#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660"=
>{</span><span style=3D"color:#008">return</span><span style=3D"color:#000"=
> x </span><span style=3D"color:#660">+</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#066">2</span><span style=3D"color:#660">;};</sp=
an><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color=
:#008">return</span><span style=3D"color:#000"> </span><span style=3D"color=
:#066">0</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"><br></span><span style=3D"color:#660">}</span></div></code></div><br>In t=
hat case, the `func2` elicits a compilation error.<br><br><a href=3D"http:/=
/ideone.com/VMGTsV" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fideone.com%2FVMGTsV\=
46sa\75D\46sntz\0751\46usg\75AFQjCNHyuOT-Sr5H9tGJrHRkr7jeeXytAw';return=
true;" onclick=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2=
F%2Fideone.com%2FVMGTsV\46sa\75D\46sntz\0751\46usg\75AFQjCNHyuOT-Sr5H9tGJrH=
Rkr7jeeXytAw';return true;">If you explicitly use SFINAE</a>:<br><br><d=
iv 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:#800">#include</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#080"><iostream></span><span style=3D"color:#000"><=
br></span><span style=3D"color:#800">#include</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#080"><string></span><span style=3D"=
color:#000"><br></span><span style=3D"color:#800">#include</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#080"><functional></spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#008">using</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#008">namespace=
</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">;</=
span><span style=3D"color:#000"><br>=C2=A0<br></span><span style=3D"color:#=
008">int</span><span style=3D"color:#000"> main</span><span style=3D"color:=
#660">()</span><span style=3D"color:#000"><br></span><span style=3D"color:#=
660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span styl=
e=3D"color:#800">// your code goes here</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#008">function</span><span style=3D"color:#660"><</span><span =
style=3D"color:#008">int</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#008">int</span><span style=3D"color:#660">)></span><span st=
yle=3D"color:#000"> func1 </span><span style=3D"color:#660">=3D</span><span=
style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D=
"color:#660">[](</span><span style=3D"color:#008">auto</span><span style=3D=
"color:#000"> x</span><span style=3D"color:#660">)</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">-></span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">decltype</span><span style=3D"co=
lor:#660">(</span><span style=3D"color:#000">x </span><span style=3D"color:=
#660">+</span><span style=3D"color:#000"> </span><span style=3D"color:#066"=
>2</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">{</span><span style=3D"color:#008">return</s=
pan><span style=3D"color:#000"> x </span><span style=3D"color:#660">+</span=
><span style=3D"color:#000"> </span><span style=3D"color:#066">2</span><spa=
n style=3D"color:#660">;};</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 std</span><span style=3D"color:#660">::</span><span style=3D"color:#008=
">function</span><span style=3D"color:#660"><</span><span style=3D"color=
:#000">std</span><span style=3D"color:#660">::</span><span style=3D"color:#=
008">string</span><span style=3D"color:#660">(</span><span style=3D"color:#=
000">std</span><span style=3D"color:#660">:<wbr>:</span><span style=3D"colo=
r:#008">string</span><span style=3D"color:#660">)></span><span style=3D"=
color:#000"> func2 </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#660">[](</span><span style=3D"color:#008">auto</span><span style=3D"color=
:#000"> x</span><span style=3D"color:#660">)</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">-></span><span style=3D"color:#000=
"> </span><span style=3D"color:#008">decltype</span><span style=3D"color:#6=
60">(</span><span style=3D"color:#000">x </span><span style=3D"color:#660">=
+</span><span style=3D"color:#000"> </span><span style=3D"color:#066">2</sp=
an><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">{</span><span style=3D"color:#008">return</span><s=
pan style=3D"color:#000"> x </span><span style=3D"color:#660">+</span><span=
style=3D"color:#000"> </span><span style=3D"color:#066">2</span><span styl=
e=3D"color:#660">;};</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">return</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#066">0</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span></d=
iv></code></div><br>Guess what? You <i>still get a compiler error.</i> `fun=
c2`'s initialization is just as incorrect as before.<br><br>The only di=
fference is the quality of the error.<br></div></blockquote><div><br>And to=
be honest, I can't even say that the error quality for the SFINAE case=
is an improvement. Oh sure, there isn't a gigantic error spew. But at =
least the error spew tells you that it's a template instantiation probl=
em. With SFINAE, the compiler just points at the line and says that it coul=
dn't do it.<br><br>With concepts, the error will be obvious: the type y=
ou passed does not provide the concept due to the failure to do X.<br></div=
>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_294_864047818.1446681022576--
------=_Part_293_471279124.1446681022576--
.
Author: Tomasz <tomaszkam@gmail.com>
Date: Wed, 4 Nov 2015 21:56:27 -0800 (PST)
Raw View
------=_Part_514_676864680.1446702987622
Content-Type: multipart/alternative;
boundary="----=_Part_515_1368763621.1446702987623"
------=_Part_515_1368763621.1446702987623
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, November 5, 2015 at 12:46:07 AM UTC+1, Nicol Bolas wrote:
>
> On Wednesday, November 4, 2015 at 5:47:35 PM UTC-5, Tomasz wrote:
>>
>> On Wednesday, November 4, 2015 at 7:39:19 PM UTC+1, Nicol Bolas wrote:
>>>
>>> On Wednesday, November 4, 2015 at 11:20:27 AM UTC-5, Tomasz wrote:
>>>>
>>>> W dniu =C5=9Broda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik Nic=
ol Bolas=20
>>>> napisa=C5=82:
>>>>>
>>>>> On Wednesday, November 4, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:
>>>>>>
>>>>>> W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytkownik N=
icol Bolas=20
>>>>>> napisa=C5=82:
>>>>>>
>>>>> One reason we don't do that, why we explicitly limit SFINAE to=20
>>>>>>> parameters/return types, is so that we don't get false positives. I=
f it=20
>>>>>>> gets past the signature, then any errors that happen ought to be re=
al,=20
>>>>>>> genuine errors that a user has to face. That is, someone did someth=
ing=20
>>>>>>> *wrong*.
>>>>>>>
>>>>>> And I am requesting and SFINAE for return type for function using=20
>>>>>> return type deduction.
>>>>>>
>>>>>
>>>>> That didn't address my point. Just because a function uses return typ=
e=20
>>>>> deduction doesn't mean it can't get false positives.=20
>>>>>
>>>>> Not everyone's functions that use return type deduction are tiny.
>>>>>
>>>>> If you give someone a type and they try to default construct it and=
=20
>>>>>>> that fails, then either your template function did something wrong =
or the=20
>>>>>>> user passed an inappropriate type. Either way, it should hard error=
out. We=20
>>>>>>> (will) have concepts to check things like that in the future, so ha=
ving a=20
>>>>>>> hard error is the right thing. The declaration should not simply di=
sappear.
>>>>>>>
>>>>>>
>>>>>> Have you checked Motivation 3 regarding the concepts. Lack of SFINAE=
=20
>>>>>> for return type deduction essentially breaks concept for generic lam=
bda=20
>>>>>> uses, And I do not think that users will constrain every lambda they=
will=20
>>>>>> write.=20
>>>>>>
>>>>>
>>>>> I don't see the idea behind Motivation 3. It seems like an admission=
=20
>>>>> that proper use of concepts will effectively solve the problem. Then =
you=20
>>>>> just declare that people won't always use them.
>>>>>
>>>>> My response to that is... tough. If we give people a tool that fixes =
a=20
>>>>> problem, and they refuse to use that tool to fix that exact problem, =
I=20
>>>>> refuse to care that they still have the problem.
>>>>>
>>>>
>>>> Lambda was created as a tool for creating ad-hoc functor for use with=
=20
>>>> STL algorithm in local scope, so requiring them to be constrained, wil=
l=20
>>>> lead to an explosion of ad-hoc constrains, that cannot be declared loc=
ally,=20
>>>> i.e. lead to C++11 design.
>>>>
>>>
>>> Here's what I don't understand about this.
>>>
>>> You don't want this feature to allow SFINAE overloading. You don't want=
=20
>>> this feature to make erroneous code less erroneous (code that triggers =
your=20
>>> auto-SFINAE will fail to instantiate something, which is still an error=
).=20
>>> The *only thing* this feature does is change what the error message you=
=20
>>> get is.
>>>
>>> I am not wanting to allow SFINAE overloading on the function body, i.e.=
,=20
>> allow following two declarations to be present and unambiguous:
>> template<typename T>
>> auto f(T x) { return x =3D=3D 2; }
>>
>> template<typename T>
>> auto f(T x) { return x =3D=3D std::string("2"); }
>> As this is requiring the whole body to be mangled into signature,=20
>> introduces full instatiation as part of overload resolution and other=20
>> problems listed in this thread.
>>
>> However, my proposal is allowing second level of SFINAE overloads, that=
=20
>> makes overload depended on validity of other expression. For example=20
>> template constuctor of std::function<int(int)> from type U is viable onl=
y=20
>> if U can be called with int and returns an int. To check that, return ty=
pe=20
>> of the function needs to be determined anyway, and I am requiring that, =
if=20
>> this leads to template instantiation, then error produced during it will=
=20
>> lead to elimination of overload, instead of hard error.
>>
>> This will lead to existing C++14 library features to work with generic=
=20
>> lambdas (see motivation 1). That changes does not only change error mess=
age.
>>
>
> That does change only the error message. Just look at your example of=20
> std::function.
>
> If no SFINAE is involved, you get this <http://ideone.com/jHTUVV>:
>
> #include <iostream>
> #include <string>
> #include <functional>
> using namespace std;
> =20
> int main()
> {
> // your code goes here
> std::function<int(int)> func1 =3D
> [](auto x) {return x + 2;};
> std::function<std::string(std::string)> func2 =3D
> [](auto x) {return x + 2;};
> return 0;
> }
>
> In that case, the `func2` elicits a compilation error.
>
> If you explicitly use SFINAE <http://ideone.com/VMGTsV>:
>
> #include <iostream>
> #include <string>
> #include <functional>
> using namespace std;
> =20
> int main()
> {
> // your code goes here
> std::function<int(int)> func1 =3D
> [](auto x) -> decltype(x + 2) {return x + 2;};
> std::function<std::string(std::string)> func2 =3D
> [](auto x) -> decltype(x + 2) {return x + 2;};
> return 0;
> }
>
> Guess what? You *still get a compiler error.* `func2`'s initialization is=
=20
> just as incorrect as before.
>
> The only difference is the quality of the error.
>
Could you please at least take a look on the code example that I have=20
presented in first post? There are links to life example there.
It present example when we have overloaded function:
void foo(std::function<int(int)>); //1
void foo(std::function<std::string(std::string)>); //2
Which may be considered (modulo perfect forwading as equivalent to)
template<typename F>
std::enable_if_t<std::is_convertible<std::result_of_t<F&(int)>,=20
int>::value, void> foo(F); //1
template<typename F>
std::enable_if_t<std::is_convertible<std::result_of_t<F&(std::string)>,=20
std::string>::value, void> foo(F); //2
And then we perform a call:
foo([](auto x) -> decltype(x+2) { return x + 2; });
Then second candidate will be eliminated by SFINAE check on function=20
constructor that is equivalent to=20
std::is_convertible<std::result_of_t<F(std::string)>, std::string>, as=20
expression x+2 is not valid for std::string and lambda cannot be called. So=
=20
the first one will be called and code works.
But if do:
foo([](auto x) { return x + 2; });
Then same check on second overload, will lead to lambda body instantiation=
=20
with std::string and produce hard error from expression x+2. So we are no=
=20
longer able to preform overload resolution based on validity of call to=20
lambda. And I am proposing that this error should lead to substitution=20
failure, so for this code, again we will select overload 1.
--=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_515_1368763621.1446702987623
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Thursday, November 5, 2015 at 12:46:07 AM UTC+1, Nicol Bolas wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;">On Wednesday, November 4, 2=
015 at 5:47:35 PM UTC-5, Tomasz wrote:<blockquote class=3D"gmail_quote" sty=
le=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1e=
x">On Wednesday, November 4, 2015 at 7:39:19 PM UTC+1, Nicol Bolas wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-=
left:1px #ccc solid;padding-left:1ex">On Wednesday, November 4, 2015 at 11:=
20:27 AM UTC-5, Tomasz wrote:<blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">W dniu=
=C5=9Broda, 4 listopada 2015 16:53:46 UTC+1 u=C5=BCytkownik Nicol Bolas na=
pisa=C5=82:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:=
0.8ex;border-left:1px #ccc solid;padding-left:1ex">On Wednesday, November 4=
, 2015 at 1:12:39 AM UTC-5, Tomasz wrote:<blockquote class=3D"gmail_quote" =
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div>W dniu =C5=9Broda, 4 listopada 2015 02:06:58 UTC+1 u=C5=BCytkown=
ik Nicol Bolas napisa=C5=82:<br></div></blockquote><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-l=
eft:1ex"><div dir=3D"ltr">One reason we don't do that, why we explicitl=
y limit SFINAE to parameters/return types, is so that we don't get fals=
e positives. If it gets past the signature, then any errors that happen oug=
ht to be real, genuine errors that a user has to face. That is, someone did=
something <i>wrong</i>.<br></div></blockquote><div>And I am requesting and=
SFINAE for return type for function using return type deduction.<br></div>=
</div></blockquote><div><br>That didn't address my point. Just because =
a function uses return type deduction doesn't mean it can't get fal=
se positives. <br><br>Not everyone's functions that use return type ded=
uction are tiny.<br></div><div><br></div><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"><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">If you give someone a type and they try to default construct it and th=
at fails, then either your template function did something wrong or the use=
r passed an inappropriate type. Either way, it should hard error out. We (w=
ill) have concepts to check things like that in the future, so having a har=
d error is the right thing. The declaration should not simply disappear.<br=
></div></blockquote><div><br>Have you checked Motivation 3 regarding the co=
ncepts. Lack of SFINAE for return type deduction essentially breaks concept=
for generic lambda uses, And I do not think that users will constrain ever=
y lambda they will write. <br></div></div></blockquote><div><br>I don't=
see the idea behind Motivation 3. It seems like an admission that proper u=
se of concepts will effectively solve the problem. Then you just declare th=
at people won't always use them.<br><br>My response to that is... tough=
.. If we give people a tool that fixes a problem, and they refuse to use tha=
t tool to fix that exact problem, I refuse to care that they still have the=
problem.<br></div></blockquote><div><br>Lambda was created as a tool for c=
reating ad-hoc functor for use with STL algorithm in local scope, so requir=
ing them to be constrained, will lead to an explosion of ad-hoc constrains,=
that cannot be declared locally, i.e. lead to C++11 design.<br></div></blo=
ckquote><div><br>Here's what I don't understand about this.<br><br>=
You don't want this feature to allow SFINAE overloading. You don't =
want this feature to make erroneous code less erroneous (code that triggers=
your auto-SFINAE will fail to instantiate something, which is still an err=
or). The <i>only thing</i> this feature does is change what the error messa=
ge you get is.<br><br></div></blockquote><div>I am not wanting to allow SFI=
NAE overloading on the function body,=20
i.e., allow following two declarations to be present and unambiguous:<br>te=
mplate<typename T><br>auto f(T x) { return x =3D=3D 2; }<br><br>templ=
ate<typename T><br>auto f(T x) { return x =3D=3D std::string("2&=
quot;); }<br>As
this is requiring the whole body to be mangled into signature,=20
introduces full instatiation as part of overload resolution and other=20
problems listed in this thread.<br><br>However, my proposal is allowing=20
second level of SFINAE overloads, that makes overload depended on=20
validity of other expression. For example template constuctor of std::funct=
ion<int(int)>=20
from type U is viable only if U can be called with int and returns an int. =
To
check that, return type of the function needs to be determined anyway,=20
and I am requiring that, if this leads to template instantiation, then erro=
r=20
produced during it will lead to elimination of overload, instead of=20
hard error.<br><br>This will lead to existing C++14 library features to=20
work with generic lambdas (see motivation 1). That changes does not only
change error message.<br></div></blockquote><div><br>That does change only=
the error message. Just look at your example of std::function.<br><br><a h=
ref=3D"http://ideone.com/jHTUVV" target=3D"_blank" rel=3D"nofollow" onmouse=
down=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fideone.=
com%2FjHTUVV\46sa\75D\46sntz\0751\46usg\75AFQjCNErKQ3tjsxaCC2uLK4jE3TyT8itH=
g';return true;" onclick=3D"this.href=3D'http://www.google.com/url?=
q\75http%3A%2F%2Fideone.com%2FjHTUVV\46sa\75D\46sntz\0751\46usg\75AFQjCNErK=
Q3tjsxaCC2uLK4jE3TyT8itHg';return true;">If no SFINAE is involved, you =
get this</a>:<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"><code><div><span style=3D"color:#800">#include</span><span style=3D"=
color:#000"> </span><span style=3D"color:#080"><iostream></span><span=
style=3D"color:#000"><br></span><span style=3D"color:#800">#include</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#080"><string>=
;</span><span style=3D"color:#000"><br></span><span style=3D"color:#800">#i=
nclude</span><span style=3D"color:#000"> </span><span style=3D"color:#080">=
<functional></span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">using</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">namespace</span><span style=3D"color:#000"> std</span><span=
style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0<br></sp=
an><span style=3D"color:#008">int</span><span style=3D"color:#000"> main</s=
pan><span style=3D"color:#660">()</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0=
=C2=A0 </span><span style=3D"color:#800">// your code goes here</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#008">function</span><span style=3D"color:=
#660"><</span><span style=3D"color:#008">int</span><span style=3D"color:=
#660">(</span><span style=3D"color:#008">int</span><span style=3D"color:#66=
0">)></span><span style=3D"color:#000"> func1 </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#660">[](</span><span style=3D"color:#008">=
auto</span><span style=3D"color:#000"> x</span><span style=3D"color:#660">)=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</spa=
n><span style=3D"color:#008">return</span><span style=3D"color:#000"> x </s=
pan><span style=3D"color:#660">+</span><span style=3D"color:#000"> </span><=
span style=3D"color:#066">2</span><span style=3D"color:#660">;};</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#008">function</span><span style=3D"color:=
#660"><</span><span style=3D"color:#000">std</span><span style=3D"color:=
#660">::</span><span style=3D"color:#008">string</span><span style=3D"color=
:#660">(</span><span style=3D"color:#000">std</span><span style=3D"color:#6=
60">:<wbr>:</span><span style=3D"color:#008">string</span><span style=3D"co=
lor:#660">)></span><span style=3D"color:#000"> func2 </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#660">[](</span><span style=3D"color=
:#008">auto</span><span style=3D"color:#000"> x</span><span style=3D"color:=
#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660"=
>{</span><span style=3D"color:#008">return</span><span style=3D"color:#000"=
> x </span><span style=3D"color:#660">+</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#066">2</span><span style=3D"color:#660">;};</sp=
an><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color=
:#008">return</span><span style=3D"color:#000"> </span><span style=3D"color=
:#066">0</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"><br></span><span style=3D"color:#660">}</span></div></code></div><br>In t=
hat case, the `func2` elicits a compilation error.<br><br><a href=3D"http:/=
/ideone.com/VMGTsV" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fideone.com%2FVMGTsV\=
46sa\75D\46sntz\0751\46usg\75AFQjCNHyuOT-Sr5H9tGJrHRkr7jeeXytAw';return=
true;" onclick=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2=
F%2Fideone.com%2FVMGTsV\46sa\75D\46sntz\0751\46usg\75AFQjCNHyuOT-Sr5H9tGJrH=
Rkr7jeeXytAw';return true;">If you explicitly use SFINAE</a>:<br><br><d=
iv 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:#800">#include</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#080"><iostream></span><span style=3D"color:#000"><=
br></span><span style=3D"color:#800">#include</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#080"><string></span><span style=3D"=
color:#000"><br></span><span style=3D"color:#800">#include</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#080"><functional></spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#008">using</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#008">namespace=
</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">;</=
span><span style=3D"color:#000"><br>=C2=A0<br></span><span style=3D"color:#=
008">int</span><span style=3D"color:#000"> main</span><span style=3D"color:=
#660">()</span><span style=3D"color:#000"><br></span><span style=3D"color:#=
660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span styl=
e=3D"color:#800">// your code goes here</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#008">function</span><span style=3D"color:#660"><</span><span =
style=3D"color:#008">int</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#008">int</span><span style=3D"color:#660">)></span><span st=
yle=3D"color:#000"> func1 </span><span style=3D"color:#660">=3D</span><span=
style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D=
"color:#660">[](</span><span style=3D"color:#008">auto</span><span style=3D=
"color:#000"> x</span><span style=3D"color:#660">)</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">-></span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">decltype</span><span style=3D"co=
lor:#660">(</span><span style=3D"color:#000">x </span><span style=3D"color:=
#660">+</span><span style=3D"color:#000"> </span><span style=3D"color:#066"=
>2</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">{</span><span style=3D"color:#008">return</s=
pan><span style=3D"color:#000"> x </span><span style=3D"color:#660">+</span=
><span style=3D"color:#000"> </span><span style=3D"color:#066">2</span><spa=
n style=3D"color:#660">;};</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 std</span><span style=3D"color:#660">::</span><span style=3D"color:#008=
">function</span><span style=3D"color:#660"><</span><span style=3D"color=
:#000">std</span><span style=3D"color:#660">::</span><span style=3D"color:#=
008">string</span><span style=3D"color:#660">(</span><span style=3D"color:#=
000">std</span><span style=3D"color:#660">:<wbr>:</span><span style=3D"colo=
r:#008">string</span><span style=3D"color:#660">)></span><span style=3D"=
color:#000"> func2 </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
:#660">[](</span><span style=3D"color:#008">auto</span><span style=3D"color=
:#000"> x</span><span style=3D"color:#660">)</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">-></span><span style=3D"color:#000=
"> </span><span style=3D"color:#008">decltype</span><span style=3D"color:#6=
60">(</span><span style=3D"color:#000">x </span><span style=3D"color:#660">=
+</span><span style=3D"color:#000"> </span><span style=3D"color:#066">2</sp=
an><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">{</span><span style=3D"color:#008">return</span><s=
pan style=3D"color:#000"> x </span><span style=3D"color:#660">+</span><span=
style=3D"color:#000"> </span><span style=3D"color:#066">2</span><span styl=
e=3D"color:#660">;};</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">return</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#066">0</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span></d=
iv></code></div><br>Guess what? You <i>still get a compiler error.</i> `fun=
c2`'s initialization is just as incorrect as before.<br><br>The only di=
fference is the quality of the error.<br></div></blockquote><div><br>Could =
you please at least take a look on the code example that I have presented i=
n first post? There are links to life example there.<br><br>It present exam=
ple when we have overloaded function:<br>void foo(std::function<int(int)=
>); //1<br>void foo(std::function<std::string(std::string)>); //2<=
br><br>Which may be considered (modulo perfect forwading as equivalent to)<=
br>template<typename F><br>std::enable_if_t<std::is_convertible<=
;std::result_of_t<F&(int)>, int>::value, void> foo(F); //1<=
br><br>template<typename F><br>std::enable_if_t<std::is_convertibl=
e<std::result_of_t<F&(std::string)>, std::string>::value, v=
oid> foo(F); //2<br><br>And then we perform a call:<br>foo([](auto x) -&=
gt; decltype(x+2) { return x + 2; });<br>Then second candidate will be elim=
inated by SFINAE check on function constructor that is equivalent to std::i=
s_convertible<std::result_of_t<F(std::string)>, std::string>, a=
s expression x+2 is not valid for std::string and lambda cannot be called. =
So the first one will be called and code works.<br><br>But if do:<br>foo([]=
(auto x) { return x + 2; });<br>Then same check on second overload, will le=
ad to lambda body instantiation with std::string and produce hard error fro=
m expression x+2. So we are no longer able to preform overload resolution b=
ased on validity of call to lambda. And I am proposing that this error shou=
ld lead to substitution failure, so for this code, again we will select ove=
rload 1.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_515_1368763621.1446702987623--
------=_Part_514_676864680.1446702987622--
.