[Config] N3276 decltype support on VC++ 11

IIRC, Stephan said that VC++ 11 supports N3276 decltype. Shall we "undef" BOOST_NO_CXX11_DECLTYPE_N3276 for VC++ 11? This enables automatic use of decltype-based `boost::result_of`. Trivial patch attached. Regards, Michel

On Aug 31, 2012, at 1:04 PM, Michel Morin wrote:
IIRC, Stephan said that VC++ 11 supports N3276 decltype.
Shall we "undef" BOOST_NO_CXX11_DECLTYPE_N3276 for VC++ 11? This enables automatic use of decltype-based `boost::result_of`. Trivial patch attached.
Nice! Can someone verify that there are no regressions in the test suit on VC++ 11? Assuming everything's OK, I'd say feel free to commit the patch, Michel. - Daniel

On 8/31/2012 10:22 AM, Daniel Walker wrote:
On Aug 31, 2012, at 1:04 PM, Michel Morin wrote:
IIRC, Stephan said that VC++ 11 supports N3276 decltype.
Shall we "undef" BOOST_NO_CXX11_DECLTYPE_N3276 for VC++ 11? This enables automatic use of decltype-based `boost::result_of`. Trivial patch attached.
Nice! Can someone verify that there are no regressions in the test suit on VC++ 11? Assuming everything's OK, I'd say feel free to commit the patch, Michel.
It's one thing to try this change on trunk ... and release even. However, until [77905] and [78195] are merged to release, boost::result_of will not use decltype for msvc or any other compiler for that matter. The reason that hasn't been done is because it's known to break some boost libraries. The last I checked, Phoenix was broken by a decltype-based result_of. From the looks of the Sandia-darwin-clang-trunk-c++11 results for trunk, that is apparently still the case. I'm tempted to simply merge the changes, the odd breakage here and there be damned. We stand a bigger risk with such a fundamental piece of infrastructure differing between trunk and release, IMO. Thoughts? -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
I'm tempted to simply merge the changes, the odd breakage here and there be damned. We stand a bigger risk with such a fundamental piece of infrastructure differing between trunk and release, IMO. Thoughts?
I couldn't expect proper fixes for decltype-based result_of compatibility will take place soon. So, if we push the result_of change into the release branch, shouldn't we replace `result_of` with `tr1_result_of` for the breaking components ? Regards, Michel

Daniel Walker wrote:
Can someone verify that there are no regressions in the test suit on VC++ 11?
As Eric said, let's try this on the trunk test runners ;) P.S. For a function `const int f()`, `decltype(f())` returns `int` on VC++ 11. So some `result_of` tests fail as in #6754. ( https://svn.boost.org/trac/boost/ticket/6754 ) Clang 3.1 and gcc 4.7-4.8 behaves similarly, and this behavior conforms to the C++11 Standard. Regards, Michel

On Sep 1, 2012, at 12:47 AM, Michel Morin wrote:
Daniel Walker wrote:
Can someone verify that there are no regressions in the test suit on VC++ 11?
As Eric said, let's try this on the trunk test runners ;)
I always run the tests before committing a patch to trunk. That's all I was asking. :)
P.S. For a function `const int f()`, `decltype(f())` returns `int` on VC++ 11. So some `result_of` tests fail as in #6754. ( https://svn.boost.org/trac/boost/ticket/6754 )
Clang 3.1 and gcc 4.7-4.8 behaves similarly, and this behavior conforms to the C++11 Standard.
Fixed. This is important. Thanks for the reminder! Eric, I'm comfortable with the state of result_of on trunk, if you want to sync it with release. I suppose now is as good a time as any, but I'll trust your judgement on the timing. - Daniel

On 9/1/2012 1:39 PM, Daniel Walker wrote:
Eric, I'm comfortable with the state of result_of on trunk, if you want to sync it with release. I suppose now is as good a time as any, but I'll trust your judgement on the timing.
Thanks, Daniel. I thought about it some and decided to merge the change to release, even though it breaks Phoenix on modern compilers. I decided that ultimately, it was more important that boost::result_of work with C++11 lambdas. We can't bugs in 1 or 2 libraries hold up progress for everybody. We will have to make a very BOLD announcement in the release notes of 1.52. Not only will users of Phoenix be affected; anybody who relies on boost::result_of to use the TR1 protocol will be broken by this. This might be a painful transition for some, but there's no helping that. I also hope that we won't have to ship a broken Phoenix in 1.52 -- that the Phoenix maintainers will step up and fix it. Joel, Thomas? Daniel, I took the liberty of merging your [80352] to release also. I know it hasn't had a chance to cycle yet, but since it only changes docs and tests, it seemed ok to me. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 9/2/12 7:24 AM, Eric Niebler wrote:
On 9/1/2012 1:39 PM, Daniel Walker wrote:
Eric, I'm comfortable with the state of result_of on trunk, if you want to sync it with release. I suppose now is as good a time as any, but I'll trust your judgement on the timing.
Thanks, Daniel. I thought about it some and decided to merge the change to release, even though it breaks Phoenix on modern compilers. I decided that ultimately, it was more important that boost::result_of work with C++11 lambdas. We can't bugs in 1 or 2 libraries hold up progress for everybody.
We will have to make a very BOLD announcement in the release notes of 1.52. Not only will users of Phoenix be affected; anybody who relies on boost::result_of to use the TR1 protocol will be broken by this. This might be a painful transition for some, but there's no helping that.
I have no problem with this as long as there's clear documentation on what users would expect and how to deal with them in their code.
I also hope that we won't have to ship a broken Phoenix in 1.52 -- that the Phoenix maintainers will step up and fix it. Joel, Thomas?
Sure, let's do it. Thomas? Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

Joel de Guzman wrote:
I also hope that we won't have to ship a broken Phoenix in 1.52 -- that the Phoenix maintainers will step up and fix it. Joel, Thomas?
Sure, let's do it. Thomas?
Joel, Fusion's invoke test (libs/fusion/test/invoke.test) fails with decltype-based result_of. The reason of the test failure is that fusion::invoke tries to instantiate boost::result_of with uncallable signatures. (Just making boost::result_of SFINAE-able does not solve the problem.) Here is a minimal test case: #include <boost/fusion/include/invoke.hpp> #include <boost/fusion/include/vector.hpp> struct F { typedef void result_type; void operator()(int&) const {} }; int main (int argc, char* argv[]) { boost::fusion::vector<int> v(1); // Error when decltype-based result_of is used; // trying to instantiate result_of<F(const int&)> boost::fusion::invoke(F(), v); return 0; } But, to be more precise, the above problem also happens with TR1-style result_of. For example, the following code fails to compile even with TR1-style result_of. #include <boost/fusion/include/invoke.hpp> #include <boost/fusion/include/vector.hpp> struct F { template <typename Sig> struct result; template <typename This> struct result<This(int&)> { typedef void type; }; void operator()(int&) const {} }; int main (int argc, char* argv[]) { boost::fusion::vector<int> v(1); // Error; // trying to instantiate result_of<F(const int&)> boost::fusion::invoke(F(), v); return 0; } And here is a related ticket https://svn.boost.org/trac/boost/ticket/6915 Regards, Michel

On 9/3/2012 11:10 AM, Michel Morin wrote:
Joel de Guzman wrote:
I also hope that we won't have to ship a broken Phoenix in 1.52 -- that the Phoenix maintainers will step up and fix it. Joel, Thomas?
Sure, let's do it. Thomas?
Joel, Fusion's invoke test (libs/fusion/test/invoke.test) fails with decltype-based result_of.
The reason of the test failure is that fusion::invoke tries to instantiate boost::result_of with uncallable signatures. (Just making boost::result_of SFINAE-able does not solve the problem.)
Here is a minimal test case: [snip]
And here is a related ticket https://svn.boost.org/trac/boost/ticket/6915
I'm not the author and maintainer of fusion::invoke (in fusion functional). It's Tobias Schwinger. I'm CC'ing him. Tobias, can you please take a look? TBH, I am not following this thread closely so I am not intimate with issues. Could anyone point me to some documentation that will bring me up to speed please? Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On 9/2/2012 9:07 PM, Joel de Guzman wrote:
TBH, I am not following this thread closely so I am not intimate with issues. Could anyone point me to some documentation that will bring me up to speed please?
Just check the result_of docs: http://www.boost.org/doc/libs/1_51_0/libs/utility/utility.htm#result_of "In a future release, BOOST_RESULT_OF_USE_DECLTYPE may be enabled by default on compilers that support decltype, so if you use the above [TR1] protocol please take care to ensure that the result_type and result<> members accurately represent the result type." That future release is 1.52. The nested result_type and result<> templates will now be ignored on modern compilers. Instead, boost::result_of uses decltype to deduce the return type of operator() directly. I should also say that it has *always* been the case that the nested result_type and result<> templates have been required to accurately report operator()'s return type. Function objects that flout this rule are buggy and always have been. This is nothing new. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 9/3/2012 12:07 PM, Joel de Guzman wrote:
On 9/3/2012 11:10 AM, Michel Morin wrote:
Joel, Fusion's invoke test (libs/fusion/test/invoke.test) fails with decltype-based result_of.
The reason of the test failure is that fusion::invoke tries to instantiate boost::result_of with uncallable signatures. (Just making boost::result_of SFINAE-able does not solve the problem.)
Here is a minimal test case: [snip]
And here is a related ticket https://svn.boost.org/trac/boost/ticket/6915
Ok I fixed the fusion::invoke test. Tricky! That also fixes the first test from Ticket #6915. The second, OTOH, I think is an error. Essentially, what the OP wants is something like this to work (i.e. compile and call the fallback overload): #include <boost/utility/result_of.hpp> int foo(int); struct junk {}; template <typename F, typename Arg> typename boost::result_of<F(Arg)>::type call(int) { return F(Arg()); } template <typename F, typename Arg> void call(long) { // fallback } int main() { call<int(*)(int), junk>(123); } And so you get: error: cannot convert 'junk' to 'int' in argument passing That IMO is the correct behavior. If not, then boost::result_of is wrong. However! This makes the current result_of code not an exact replacement to decltype which allows this variation of above: #include <boost/utility/result_of.hpp> int foo(int); struct junk {}; template <typename F, typename Arg> decltype(F(Arg())) call(int) { return F(Arg()); } template <typename F, typename Arg> void call(long) { // fallback } int main() { call<int(*)(int), junk>(123); } So, there's your problem. If Fusion's invoke used decltype instead of result_of, it would have worked. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

Joel de Guzman wrote:
Ok I fixed the fusion::invoke test. Tricky!
That also fixes the first test from Ticket #6915. The second, OTOH, I think is an error.
I didn't have a closer look at #6915, so I cannot answer about the ticket (sorry!). But the following test case still fails: (Test case attached.) Michel Morin wrote:
Here is a minimal test case:
#include <boost/fusion/include/invoke.hpp> #include <boost/fusion/include/vector.hpp>
struct F { typedef void result_type; void operator()(int&) const {} };
int main (int argc, char* argv[]) { boost::fusion::vector<int> v(1); // Error when decltype-based result_of is used; // trying to instantiate result_of<F(const int&)> boost::fusion::invoke(F(), v);
return 0; }
Regards, Michel

On 9/4/2012 11:23 PM, Michel Morin wrote:
Joel de Guzman wrote:
Ok I fixed the fusion::invoke test. Tricky!
That also fixes the first test from Ticket #6915. The second, OTOH, I think is an error.
I didn't have a closer look at #6915, so I cannot answer about the ticket (sorry!). But the following test case still fails: (Test case attached.)
Yes, and I know why. Answer my concerns first (prior post) and I'll continue on the whys. For now, I need a rest :-) Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

Joel de Guzman wrote:
I didn't have a closer look at #6915, so I cannot answer about the ticket (sorry!). But the following test case still fails: (Test case attached.)
Yes, and I know why. Answer my concerns first (prior post) and I'll continue on the whys.
For now, I need a rest :-)
OK. Joel de Guzman wrote:
However! This makes the current result_of code not an exact replacement to decltype which allows this variation of above:
Right. boost/std::result_of is not an exact replacement to decltype, since decltype allows SFINAE but boost/std::result_of doesn't. [...]
If Fusion's invoke used decltype instead of result_of, it would have worked.
I tried to compile my test case for fusion::invoke with SFINAE-enabled result_of, but it failed to compile. After adding a "fallback type" to SFINAE-enabled result_of, then the test case runs fine. Regards, Michel

On 9/5/2012 12:53 AM, Michel Morin wrote:
Joel de Guzman wrote:
However! This makes the current result_of code not an exact replacement to decltype which allows this variation of above:
Right. boost/std::result_of is not an exact replacement to decltype, since decltype allows SFINAE but boost/std::result_of doesn't.
[...]
If Fusion's invoke used decltype instead of result_of, it would have worked.
I tried to compile my test case for fusion::invoke with SFINAE-enabled result_of, but it failed to compile. After adding a "fallback type" to SFINAE-enabled result_of, then the test case runs fine.
The following code (attached) demonstrates the problem of Fusion::invoke with the current decltype based result_of. Comment out the first line for the code to use plain decltype vs. result_of. Notice that because result_of does not allow SFINAE, it barfs when the compiler tries the first overload of invoke (substitution failure). The compiler could have chosen the second overload. I see no other way to get around this problem of result_of. I am getting inclined to use decltype directly in fusion instead of going through result_of. Problems like this kinda defeats the purpose of decltype-ifying result_of, but heck. The question is: should we allow SFINAE for result_of. I think now that we should. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On Tue, Sep 4, 2012 at 5:01 PM, Joel de Guzman <djowel@gmail.com> wrote:
On 9/5/2012 12:53 AM, Michel Morin wrote:
Joel de Guzman wrote:
However! This makes the current result_of code not an exact replacement to decltype which allows this variation of above:
Right. boost/std::result_of is not an exact replacement to decltype, since decltype allows SFINAE but boost/std::result_of doesn't.
[...]
If Fusion's invoke used decltype instead of result_of, it would have worked.
I tried to compile my test case for fusion::invoke with SFINAE-enabled result_of, but it failed to compile. After adding a "fallback type" to SFINAE-enabled result_of, then the test case runs fine.
The following code (attached) demonstrates the problem of Fusion::invoke with the current decltype based result_of.
It seems like the fact that it worked with the TR1-protocol-based result_of was brittle at best. Replace foo with a function object with a properly restricted result template and it likely wouldn't work with TR1-protocol-based result_of, either. Comment
out the first line for the code to use plain decltype vs. result_of. Notice that because result_of does not allow SFINAE, it barfs when the compiler tries the first overload of invoke (substitution failure). The compiler could have chosen the second overload.
Wasn't this fact (the difference between result_of and decltype) already pointed out earlier in this thread?
I see no other way to get around this problem of result_of. I am getting inclined to use decltype directly in fusion instead of going through result_of. Problems like this kinda defeats the purpose of decltype-ifying result_of, but heck.
Is this a recently discovered problem with the use of result_of in Fusion? How come it didn't come up before? The question is: should we allow SFINAE for result_of. I think now
that we should.
Wouldn't this create a portability problem between C++03 and C++11? Or are you suggesting this for C++11-only code? Or are you suggesting to likewise modify result_of in C++03 to allow SFINAE, via something like Eric's can_be_called metafunction? - Jeff

On 9/5/2012 9:03 AM, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Sep 4, 2012 at 5:01 PM, Joel de Guzman <djowel@gmail.com> wrote:
On 9/5/2012 12:53 AM, Michel Morin wrote:
Joel de Guzman wrote:
However! This makes the current result_of code not an exact replacement to decltype which allows this variation of above:
Right. boost/std::result_of is not an exact replacement to decltype, since decltype allows SFINAE but boost/std::result_of doesn't.
[...]
If Fusion's invoke used decltype instead of result_of, it would have worked.
I tried to compile my test case for fusion::invoke with SFINAE-enabled result_of, but it failed to compile. After adding a "fallback type" to SFINAE-enabled result_of, then the test case runs fine.
The following code (attached) demonstrates the problem of Fusion::invoke with the current decltype based result_of.
It seems like the fact that it worked with the TR1-protocol-based result_of was brittle at best. Replace foo with a function object with a properly restricted result template and it likely wouldn't work with TR1-protocol-based result_of, either.
Wrong. TR1 result-of works with function objects. See attached. It works with both nested result_type and struct result; The reason it works is that TR1 result_of does not attempt the match the argument types on invalid (substitution failure) overload selection.
Comment
out the first line for the code to use plain decltype vs. result_of. Notice that because result_of does not allow SFINAE, it barfs when the compiler tries the first overload of invoke (substitution failure). The compiler could have chosen the second overload.
Wasn't this fact (the difference between result_of and decltype) already pointed out earlier in this thread?
I don't know. All I am saying is that this poses real problems that go beyond correct usage of result_of. I do not have time to look through all the posts in this thread.
I see no other way to get around this problem of result_of. I am getting inclined to use decltype directly in fusion instead of going through result_of. Problems like this kinda defeats the purpose of decltype-ifying result_of, but heck.
Is this a recently discovered problem with the use of result_of in Fusion?
Yes.
How come it didn't come up before?
Because BOOST_RESULT_OF_USE_DECLTYPE wasn't there before.
The question is: should we allow SFINAE for result_of. I think now
that we should.
Wouldn't this create a portability problem between C++03 and C++11? Or are you suggesting this for C++11-only code? Or are you suggesting to likewise modify result_of in C++03 to allow SFINAE, via something like Eric's can_be_called metafunction?
I don't know. I will not have enough time to follow through with this anyway so I'll leave it to the result_of people to "do the right thing". In any case, I can work out a solution/workaround. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On Tue, Sep 4, 2012 at 7:00 PM, Joel de Guzman <djowel@gmail.com> wrote:
On 9/5/2012 9:03 AM, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Sep 4, 2012 at 5:01 PM, Joel de Guzman <djowel@gmail.com> wrote:
On 9/5/2012 12:53 AM, Michel Morin wrote:
Joel de Guzman wrote:
However! This makes the current result_of code not an exact replacement
to decltype which allows this variation of above:
Right. boost/std::result_of is not an exact replacement to decltype, since decltype allows SFINAE but boost/std::result_of doesn't.
(*)
[...]
If Fusion's invoke used decltype instead of
result_of, it would have worked.
I tried to compile my test case for fusion::invoke with SFINAE-enabled result_of, but it failed to compile. After adding a "fallback type" to SFINAE-enabled result_of, then the test case runs fine.
The following code (attached) demonstrates the problem of Fusion::invoke with the current decltype based result_of.
It seems like the fact that it worked with the TR1-protocol-based result_of was brittle at best. Replace foo with a function object with a properly restricted result template and it likely wouldn't work with TR1-protocol-based result_of, either.
Wrong. TR1 result-of works with function objects. See attached. It works with both nested result_type and struct result;
Eh, that's why I said, "properly restricted". Replace the result specialization with anything that disallows the erroneous binding and it fails. E.g., template< class This > struct result< This ( int & ) > { typedef int type; }; By the way, your given specialization of result, template <typename T> struct result<foo(T&)> { typedef int type; }; is not correct. It will fail for result_of< F const ( Arg& ) >::type (should one decide to use a const-qualified function object), even though this is a valid call signature. In any case, I still think your use of result_of in the given example was brittle and, ultimately, a misuse, whether we're speaking of the TR1-based or the decltype-based result_of. AFAIK, result_of has never had any guarantees as far as instantiating it with invalid call signatures. The reason it works is that TR1 result_of does not attempt the
match the argument types on invalid (substitution failure) overload selection.
But, it could, and more importantly, there's certainly no guarantee that it *won't*, either directly within the result_of implementation or implicitly by virtue of the available result specializations. Comment
out the first line for the code to use plain decltype vs. result_of. Notice that because result_of does not allow SFINAE, it barfs when the compiler tries the first overload of invoke (substitution failure). The compiler could have chosen the second overload.
Wasn't this fact (the difference between result_of and decltype) already pointed out earlier in this thread?
I don't know. All I am saying is that this poses real problems that go beyond correct usage of result_of. I do not have time to look through all the posts in this thread.
See (*) above, which you quoted :/ I see no other way to get around this problem of result_of. I am
getting inclined to use decltype directly in fusion instead of going through result_of. Problems like this kinda defeats the purpose of decltype-ifying result_of, but heck.
Is this a recently discovered problem with the use of result_of in Fusion?
Yes.
How come it didn't come up before?
Because BOOST_RESULT_OF_USE_DECLTYPE wasn't there before.
May we inspect a typical use of result_of that was working before and isn't now? The question is: should we allow SFINAE for result_of. I think now
that we should.
Wouldn't this create a portability problem between C++03 and C++11? Or are you suggesting this for C++11-only code? Or are you suggesting to likewise modify result_of in C++03 to allow SFINAE, via something like Eric's can_be_called metafunction?
I don't know. I will not have enough time to follow through with this anyway so I'll leave it to the result_of people to "do the right thing". In any case, I can work out a solution/workaround.
You can't just make a proposal and then crawl back in your cave :) - Jeff

On Tue, Sep 4, 2012 at 7:32 PM, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
On Tue, Sep 4, 2012 at 7:00 PM, Joel de Guzman <djowel@gmail.com> wrote:
On 9/5/2012 9:03 AM, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Sep 4, 2012 at 5:01 PM, Joel de Guzman <djowel@gmail.com> wrote:
[...]
The following code (attached) demonstrates the problem of
Fusion::invoke with the current decltype based result_of.
[...]
Comment
out the first line for the code to use plain decltype vs. result_of. Notice that because result_of does not allow SFINAE, it barfs when the compiler tries the first overload of invoke (substitution failure). The compiler could have chosen the second overload.
[...]
I see no other way to get around this problem of result_of. I am
getting inclined to use decltype directly in fusion instead of going through result_of. Problems like this kinda defeats the purpose of decltype-ifying result_of, but heck.
Is this a recently discovered problem with the use of result_of in Fusion?
Yes.
How come it didn't come up before?
Because BOOST_RESULT_OF_USE_DECLTYPE wasn't there before.
May we inspect a typical use of result_of that was working before and isn't now?
Actually, upon thinking about the larger context, I see where this could easily happen (sorry for being dense, Joel)... - I'm surprised it didn't fail TR1-based result_of more often :/ - I don't know how to fix it for TR1-based result_of except using something like Eric's can_be_called metafunction. - Jeff

On 9/5/2012 10:32 AM, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Sep 4, 2012 at 7:00 PM, Joel de Guzman <djowel@gmail.com> wrote:
On 9/5/2012 9:03 AM, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Sep 4, 2012 at 5:01 PM, Joel de Guzman <djowel@gmail.com> wrote:
On 9/5/2012 12:53 AM, Michel Morin wrote:
Joel de Guzman wrote:
However! This makes the current result_of code not an exact replacement
to decltype which allows this variation of above:
Right. boost/std::result_of is not an exact replacement to decltype, since decltype allows SFINAE but boost/std::result_of doesn't.
(*)
[...]
If Fusion's invoke used decltype instead of
result_of, it would have worked.
I tried to compile my test case for fusion::invoke with SFINAE-enabled result_of, but it failed to compile. After adding a "fallback type" to SFINAE-enabled result_of, then the test case runs fine.
The following code (attached) demonstrates the problem of Fusion::invoke with the current decltype based result_of.
It seems like the fact that it worked with the TR1-protocol-based result_of was brittle at best. Replace foo with a function object with a properly restricted result template and it likely wouldn't work with TR1-protocol-based result_of, either.
Wrong. TR1 result-of works with function objects. See attached. It works with both nested result_type and struct result;
Eh, that's why I said, "properly restricted". Replace the result specialization with anything that disallows the erroneous binding and it fails. E.g.,
template< class This > struct result< This ( int & ) > { typedef int type; };
By the way, your given specialization of result,
template <typename T> struct result<foo(T&)> { typedef int type; };
is not correct. It will fail for result_of< F const ( Arg& ) >::type (should one decide to use a const-qualified function object), even though this is a valid call signature.
In any case, I still think your use of result_of in the given example was brittle and, ultimately, a misuse, whether we're speaking of the TR1-based or the decltype-based result_of. AFAIK, result_of has never had any guarantees as far as instantiating it with invalid call signatures.
Heh, I know you'd point that out. I should've been more careful when constructing the result struct. I was in a hurry. Anyway, I see your point.
The reason it works is that TR1 result_of does not attempt the
match the argument types on invalid (substitution failure) overload selection.
But, it could, and more importantly, there's certainly no guarantee that it *won't*, either directly within the result_of implementation or implicitly by virtue of the available result specializations.
That's a very good point.
out the first line for the code to use plain decltype vs. result_of. Notice that because result_of does not allow SFINAE, it barfs when the compiler tries the first overload of invoke (substitution failure). The compiler could have chosen the second overload.
Wasn't this fact (the difference between result_of and decltype) already pointed out earlier in this thread?
I don't know. All I am saying is that this poses real problems that go beyond correct usage of result_of. I do not have time to look through all the posts in this thread.
See (*) above, which you quoted :/
That's not "earlier in this thread". That's later in the thread.
I see no other way to get around this problem of result_of. I am
getting inclined to use decltype directly in fusion instead of going through result_of. Problems like this kinda defeats the purpose of decltype-ifying result_of, but heck.
Is this a recently discovered problem with the use of result_of in Fusion?
Yes.
How come it didn't come up before?
Because BOOST_RESULT_OF_USE_DECLTYPE wasn't there before.
May we inspect a typical use of result_of that was working before and isn't now?
Nope I do not have that yet, apart from what I already posted.
The question is: should we allow SFINAE for result_of. I think now
that we should.
Wouldn't this create a portability problem between C++03 and C++11? Or are you suggesting this for C++11-only code? Or are you suggesting to likewise modify result_of in C++03 to allow SFINAE, via something like Eric's can_be_called metafunction?
I don't know. I will not have enough time to follow through with this anyway so I'll leave it to the result_of people to "do the right thing". In any case, I can work out a solution/workaround.
You can't just make a proposal and then crawl back in your cave :)
I am not making a proposal. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On Tue, Sep 4, 2012 at 7:56 PM, Joel de Guzman <djowel@gmail.com> wrote:
On 9/5/2012 10:32 AM, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Sep 4, 2012 at 7:00 PM, Joel de Guzman <djowel@gmail.com> wrote:
On 9/5/2012 9:03 AM, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Sep 4, 2012 at 5:01 PM, Joel de Guzman <djowel@gmail.com>
wrote:
The question is: should we allow SFINAE for result_of. I think now
that we should.
Wouldn't this create a portability problem between C++03 and C++11?
Or are you suggesting this for C++11-only code? Or are you suggesting to likewise modify result_of in C++03 to allow SFINAE, via something like Eric's can_be_called metafunction?
I don't know. I will not have enough time to follow through with this anyway so I'll leave it to the result_of people to "do the right thing". In any case, I can work out a solution/workaround.
You can't just make a proposal and then crawl back in your cave :)
I am not making a proposal.
"The question is: should we allow SFINAE for result_of. I think now that we should." I took that to be a proposal. In any case, it looks like Daniel has taken a stab at it. I'm not sure if such behavior should be added to result_of itself or....maybe an entirely different utility should be created, e.g., enable_result_of or sfinae_result_of. - Jeff

On 9/4/2012 10:32 PM, Jeffrey Lee Hellrung, Jr. wrote:
In any case, I still think your use of result_of in the given example was brittle and, ultimately, a misuse, whether we're speaking of the TR1-based or the decltype-based result_of.
Yes.
AFAIK, result_of has never had any guarantees as far as instantiating it with invalid call signatures.
Correct. And in C++11, std::result_of doesn't make that guarantee either. From Table 53 in 20.7.6.6 describing the requirements of std::result_of: "Fn shall be a function object type (20.8), reference to function, or reference to function object type. The expression decltype(declval<Fn>()(declval<ArgTypes>()...)) shall be well formed." Joel, I know you're annoyed by this change. But in truth, you were relying on an implementation detail of result_of. The list of gotchas in the release notes will include this case. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 9/5/12 11:12 PM, Eric Niebler wrote:
On 9/4/2012 10:32 PM, Jeffrey Lee Hellrung, Jr. wrote:
In any case, I still think your use of result_of in the given example was brittle and, ultimately, a misuse, whether we're speaking of the TR1-based or the decltype-based result_of.
Yes.
AFAIK, result_of has never had any guarantees as far as instantiating it with invalid call signatures.
Correct. And in C++11, std::result_of doesn't make that guarantee either. From Table 53 in 20.7.6.6 describing the requirements of std::result_of:
"Fn shall be a function object type (20.8), reference to function, or reference to function object type. The expression decltype(declval<Fn>()(declval<ArgTypes>()...)) shall be well formed."
Joel, I know you're annoyed by this change. But in truth, you were relying on an implementation detail of result_of. The list of gotchas in the release notes will include this case.
I am not in anyway annoyed. I am just pointing out the problems of result_of in real code. You keep in saying "you". In fact, it's not me. That part of the code is Tobias'; The phoenix-3 code using result_of is Thomas', keep in mind that Phoenix-2 uses its own result protocol. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On 9/5/2012 12:05 PM, Joel de Guzman wrote:
On 9/5/12 11:12 PM, Eric Niebler wrote:
Joel, I know you're annoyed by this change. But in truth, you were relying on an implementation detail of result_of. The list of gotchas in the release notes will include this case.
I am not in anyway annoyed. I am just pointing out the problems of result_of in real code. You keep in saying "you". In fact, it's not me. That part of the code is Tobias'; The phoenix-3 code using result_of is Thomas', keep in mind that Phoenix-2 uses its own result protocol.
My apologies. In any case, I've described the problem along with a potential fix to the standardization committee, and cc'ed Doug. I'll be interested in hearing what they say. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Sent from a mobile device. On Sep 5, 2012, at 12:12 PM, Eric Niebler <eric@boostpro.com> wrote:
On 9/5/2012 12:05 PM, Joel de Guzman wrote:
On 9/5/12 11:12 PM, Eric Niebler wrote:
Joel, I know you're annoyed by this change. But in truth, you were relying on an implementation detail of result_of. The list of gotchas in the release notes will include this case.
I am not in anyway annoyed. I am just pointing out the problems of result_of in real code. You keep in saying "you". In fact, it's not me. That part of the code is Tobias'; The phoenix-3 code using result_of is Thomas', keep in mind that Phoenix-2 uses its own result protocol.
My apologies. In any case, I've described the problem along with a potential fix to the standardization committee, and cc'ed Doug. I'll be interested in hearing what they say.
Thanks! Could you cc me as well. I would be interest to hear the reaction. - Daniel

On Sep 4, 2012, at 8:01 PM, Joel de Guzman wrote:
On 9/5/2012 12:53 AM, Michel Morin wrote:
Joel de Guzman wrote:
However! This makes the current result_of code not an exact replacement to decltype which allows this variation of above:
Right. boost/std::result_of is not an exact replacement to decltype, since decltype allows SFINAE but boost/std::result_of doesn't.
[...]
If Fusion's invoke used decltype instead of result_of, it would have worked.
I tried to compile my test case for fusion::invoke with SFINAE-enabled result_of, but it failed to compile. After adding a "fallback type" to SFINAE-enabled result_of, then the test case runs fine.
The following code (attached) demonstrates the problem of Fusion::invoke with the current decltype based result_of. Comment out the first line for the code to use plain decltype vs. result_of. Notice that because result_of does not allow SFINAE, it barfs when the compiler tries the first overload of invoke (substitution failure). The compiler could have chosen the second overload.
I see no other way to get around this problem of result_of. I am getting inclined to use decltype directly in fusion instead of going through result_of. Problems like this kinda defeats the purpose of decltype-ifying result_of, but heck.
The question is: should we allow SFINAE for result_of. I think now that we should.
Thanks for the sample code, Joel. I don't exactly understand the problem though. Why overload invoke? Isn't this the perfect occasion to use rvalue references? invoke could be defined as follows and everything would work fine. template <typename F, typename Arg> typename boost::result_of<F(Arg&&)>::type invoke(F f, Arg&& arg) { return f(boost::forward<Arg>(arg)); } The decltype-based result_of constructs the call-expression using rvalue-references (via boost::decval) for perfect forwarding. - Daniel

On 9/5/2012 10:08 AM, Daniel Walker wrote:
On Sep 4, 2012, at 8:01 PM, Joel de Guzman wrote:
On 9/5/2012 12:53 AM, Michel Morin wrote:
Joel de Guzman wrote:
However! This makes the current result_of code not an exact replacement to decltype which allows this variation of above:
Right. boost/std::result_of is not an exact replacement to decltype, since decltype allows SFINAE but boost/std::result_of doesn't.
[...]
If Fusion's invoke used decltype instead of result_of, it would have worked.
I tried to compile my test case for fusion::invoke with SFINAE-enabled result_of, but it failed to compile. After adding a "fallback type" to SFINAE-enabled result_of, then the test case runs fine.
The following code (attached) demonstrates the problem of Fusion::invoke with the current decltype based result_of. Comment out the first line for the code to use plain decltype vs. result_of. Notice that because result_of does not allow SFINAE, it barfs when the compiler tries the first overload of invoke (substitution failure). The compiler could have chosen the second overload.
I see no other way to get around this problem of result_of. I am getting inclined to use decltype directly in fusion instead of going through result_of. Problems like this kinda defeats the purpose of decltype-ifying result_of, but heck.
The question is: should we allow SFINAE for result_of. I think now that we should.
Thanks for the sample code, Joel. I don't exactly understand the problem though. Why overload invoke? Isn't this the perfect occasion to use rvalue references? invoke could be defined as follows and everything would work fine.
template <typename F, typename Arg> typename boost::result_of<F(Arg&&)>::type invoke(F f, Arg&& arg) { return f(boost::forward<Arg>(arg)); }
The decltype-based result_of constructs the call-expression using rvalue-references (via boost::decval) for perfect forwarding.
Yes, I agree. This is the perfect occasion to use rvalue references. What you wrote is a plausible solution and one I am looking into right now (not as simple as the test code though). However... that is pretty much besides the point. And the point is that the current decltype based result_of breaks with overloads. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On Sep 4, 2012, at 10:29 PM, Joel de Guzman wrote:
On 9/5/2012 10:08 AM, Daniel Walker wrote:
On Sep 4, 2012, at 8:01 PM, Joel de Guzman wrote:
On 9/5/2012 12:53 AM, Michel Morin wrote:
Joel de Guzman wrote:
However! This makes the current result_of code not an exact replacement to decltype which allows this variation of above:
Right. boost/std::result_of is not an exact replacement to decltype, since decltype allows SFINAE but boost/std::result_of doesn't.
[...]
If Fusion's invoke used decltype instead of result_of, it would have worked.
I tried to compile my test case for fusion::invoke with SFINAE-enabled result_of, but it failed to compile. After adding a "fallback type" to SFINAE-enabled result_of, then the test case runs fine.
The following code (attached) demonstrates the problem of Fusion::invoke with the current decltype based result_of. Comment out the first line for the code to use plain decltype vs. result_of. Notice that because result_of does not allow SFINAE, it barfs when the compiler tries the first overload of invoke (substitution failure). The compiler could have chosen the second overload.
I see no other way to get around this problem of result_of. I am getting inclined to use decltype directly in fusion instead of going through result_of. Problems like this kinda defeats the purpose of decltype-ifying result_of, but heck.
The question is: should we allow SFINAE for result_of. I think now that we should.
Thanks for the sample code, Joel. I don't exactly understand the problem though. Why overload invoke? Isn't this the perfect occasion to use rvalue references? invoke could be defined as follows and everything would work fine.
template <typename F, typename Arg> typename boost::result_of<F(Arg&&)>::type invoke(F f, Arg&& arg) { return f(boost::forward<Arg>(arg)); }
The decltype-based result_of constructs the call-expression using rvalue-references (via boost::decval) for perfect forwarding.
Yes, I agree. This is the perfect occasion to use rvalue references. What you wrote is a plausible solution and one I am looking into right now (not as simple as the test code though).
However... that is pretty much besides the point. And the point is that the current decltype based result_of breaks with overloads.
OK, I think there's something we can do about this. I've attached a modification of your sample code that uses a simple is_callable metafunction predicate with enable_if so that SFINAE can kick in. It's a proof of concept. I'm not familiar with Eric's can_be_called so I don't know if these metafunctions test exactly the same thing. My is_callable tests if a valid call expression can be constructed from a result_of-style signature; i.e. can the signature be used with result_of to get a result type. Now, this could be folded into result_of; e.g. result_of could inherit from enable_if_lazy<is_callable<...>, ...>, or something like that, if you follow me. Is it worth fleshing this out? Or should we just leave it as a known (and soon to be documented) difference in behavior between TR1 and decltype-based result_of? - Daniel

On 9/5/2012 1:46 PM, Daniel Walker wrote:
On Sep 4, 2012, at 10:29 PM, Joel de Guzman wrote:
On 9/5/2012 10:08 AM, Daniel Walker wrote:
On Sep 4, 2012, at 8:01 PM, Joel de Guzman wrote:
On 9/5/2012 12:53 AM, Michel Morin wrote:
Joel de Guzman wrote:
However! This makes the current result_of code not an exact replacement to decltype which allows this variation of above:
Right. boost/std::result_of is not an exact replacement to decltype, since decltype allows SFINAE but boost/std::result_of doesn't.
[...]
If Fusion's invoke used decltype instead of result_of, it would have worked.
I tried to compile my test case for fusion::invoke with SFINAE-enabled result_of, but it failed to compile. After adding a "fallback type" to SFINAE-enabled result_of, then the test case runs fine.
The following code (attached) demonstrates the problem of Fusion::invoke with the current decltype based result_of. Comment out the first line for the code to use plain decltype vs. result_of. Notice that because result_of does not allow SFINAE, it barfs when the compiler tries the first overload of invoke (substitution failure). The compiler could have chosen the second overload.
I see no other way to get around this problem of result_of. I am getting inclined to use decltype directly in fusion instead of going through result_of. Problems like this kinda defeats the purpose of decltype-ifying result_of, but heck.
The question is: should we allow SFINAE for result_of. I think now that we should.
Thanks for the sample code, Joel. I don't exactly understand the problem though. Why overload invoke? Isn't this the perfect occasion to use rvalue references? invoke could be defined as follows and everything would work fine.
template <typename F, typename Arg> typename boost::result_of<F(Arg&&)>::type invoke(F f, Arg&& arg) { return f(boost::forward<Arg>(arg)); }
The decltype-based result_of constructs the call-expression using rvalue-references (via boost::decval) for perfect forwarding.
Yes, I agree. This is the perfect occasion to use rvalue references. What you wrote is a plausible solution and one I am looking into right now (not as simple as the test code though).
However... that is pretty much besides the point. And the point is that the current decltype based result_of breaks with overloads.
OK, I think there's something we can do about this. I've attached a modification of your sample code that uses a simple is_callable metafunction predicate with enable_if so that SFINAE can kick in. It's a proof of concept. I'm not familiar with Eric's can_be_called so I don't know if these metafunctions test exactly the same thing. My is_callable tests if a valid call expression can be constructed from a result_of-style signature; i.e. can the signature be used with result_of to get a result type.
Now, this could be folded into result_of; e.g. result_of could inherit from enable_if_lazy<is_callable<...>, ...>, or something like that, if you follow me. Is it worth fleshing this out? Or should we just leave it as a known (and soon to be documented) difference in behavior between TR1 and decltype-based result_of?
I'm not sure. To me, I think it's easier to simply avoid result_of on C++11 and just use decltype directly. Problem solved. Why use an inferior tool when something better is available anyway? Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On 9/5/2012 2:54 AM, Joel de Guzman wrote:
On 9/5/2012 1:46 PM, Daniel Walker wrote:
OK, I think there's something we can do about this. I've attached a modification of your sample code that uses a simple is_callable metafunction predicate with enable_if so that SFINAE can kick in. It's a proof of concept. I'm not familiar with Eric's can_be_called
I describe the technique here: http://www.boost.org/doc/libs/1_51_0/doc/html/proto/appendices.html#boost_pr... And there is a feature request to add this metafunction to Boost.Function_types, with reference implementation, here: https://svn.boost.org/trac/boost/ticket/3783 That ticket is now 3 years old. Tobias, any interest in it?
so I don't know if these metafunctions test exactly the same thing. My is_callable tests if a valid call expression can be constructed from a result_of-style signature; i.e. can the signature be used with result_of to get a result type.
This is a good solution.
Now, this could be folded into result_of; e.g. result_of could inherit from enable_if_lazy<is_callable<...>, ...>, or something like that, if you follow me. Is it worth fleshing this out? Or should we just leave it as a known (and soon to be documented) difference in behavior between TR1 and decltype-based result_of?
I would be opposed to folding this into boost::result_of both because of the metaprogramming overhead, and also because I don't want to encourage people to do something that will make it harder for them to port their code to std::result_of later. A separate metafunction would be useful, or an is_callable_with_args trait. That said, it's an interesting suggestion, and if I can find a light-weight solution, I might float it with the standardization committee and see if there is interest.
I'm not sure. To me, I think it's easier to simply avoid result_of on C++11 and just use decltype directly. Problem solved. Why use an inferior tool when something better is available anyway?
In the case where you need an overload to drop out because of the ill-formed-ness of a call expression, I agree with you. If you mean to swear off using result_of entirely because of this issue, then you'd be making your code non-portable for no good reason. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 9/5/12 11:33 PM, Eric Niebler wrote:
I'm not sure. To me, I think it's easier to simply avoid result_of on C++11 and just use decltype directly. Problem solved. Why use an inferior tool when something better is available anyway?
In the case where you need an overload to drop out because of the ill-formed-ness of a call expression, I agree with you. If you mean to swear off using result_of entirely because of this issue, then you'd be making your code non-portable for no good reason.
How so? I can keep using result_of in '03 code and use decltype in '11 code. I see no reason how that will be non-portable. PS> If you stop acting like the police, perhaps more people will stop behaving like renegades ;-) Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On 9/5/2012 12:14 PM, Joel de Guzman wrote:
On 9/5/12 11:33 PM, Eric Niebler wrote:
I'm not sure. To me, I think it's easier to simply avoid result_of on C++11 and just use decltype directly. Problem solved. Why use an inferior tool when something better is available anyway?
In the case where you need an overload to drop out because of the ill-formed-ness of a call expression, I agree with you. If you mean to swear off using result_of entirely because of this issue, then you'd be making your code non-portable for no good reason.
How so? I can keep using result_of in '03 code and use decltype in '11 code. I see no reason how that will be non-portable.
I mean that you can use boost::result_of everywhere except where you need to select overloads on
PS> If you stop acting like the police, perhaps more people will stop behaving like renegades ;-)
The winky-face here doesn't make that comment acceptable. Since when is maintaining a library "acting like the police"? Let me remind you: we're here because you've been neglecting the maintenance of your own libraries, Phoenix and Fusion, which have been broken by the decltype-result_of on trunk since APRIL. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 9/6/12 1:00 AM, Eric Niebler wrote:
On 9/5/2012 12:14 PM, Joel de Guzman wrote:
On 9/5/12 11:33 PM, Eric Niebler wrote:
I'm not sure. To me, I think it's easier to simply avoid result_of on C++11 and just use decltype directly. Problem solved. Why use an inferior tool when something better is available anyway?
In the case where you need an overload to drop out because of the ill-formed-ness of a call expression, I agree with you. If you mean to swear off using result_of entirely because of this issue, then you'd be making your code non-portable for no good reason.
How so? I can keep using result_of in '03 code and use decltype in '11 code. I see no reason how that will be non-portable.
I mean that you can use boost::result_of everywhere except where you need to select overloads on
So avoiding result_of == non-portable ?
PS> If you stop acting like the police, perhaps more people will stop behaving like renegades ;-)
The winky-face here doesn't make that comment acceptable. Since when is maintaining a library "acting like the police"? Let me remind you: we're here because you've been neglecting the maintenance of your own libraries, Phoenix and Fusion, which have been broken by the decltype-result_of on trunk since APRIL.
That tone is exactly my point ;-) And yes, that's another winky face. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On Sep 5, 2012, at 6:56 PM, Joel de Guzman wrote:
On 9/6/12 1:00 AM, Eric Niebler wrote:
On 9/5/2012 12:14 PM, Joel de Guzman wrote:
On 9/5/12 11:33 PM, Eric Niebler wrote:
I'm not sure. To me, I think it's easier to simply avoid result_of on C++11 and just use decltype directly. Problem solved. Why use an inferior tool when something better is available anyway?
In the case where you need an overload to drop out because of the ill-formed-ness of a call expression, I agree with you. If you mean to swear off using result_of entirely because of this issue, then you'd be making your code non-portable for no good reason.
How so? I can keep using result_of in '03 code and use decltype in '11 code. I see no reason how that will be non-portable.
I mean that you can use boost::result_of everywhere except where you need to select overloads on
So avoiding result_of == non-portable ?
result_of buys you some portability in so far as it can work in C++03 whereas decltype is purely a creature of C++11. result_of is also convenient for the common case where you just want to use perfect forwarding; e.g. it's less tedious and more readable than writing long strings of declvals wrapping your arguments inside the decltype.
PS> If you stop acting like the police, perhaps more people will stop behaving like renegades ;-)
The winky-face here doesn't make that comment acceptable. Since when is maintaining a library "acting like the police"? Let me remind you: we're here because you've been neglecting the maintenance of your own libraries, Phoenix and Fusion, which have been broken by the decltype-result_of on trunk since APRIL.
That tone is exactly my point ;-) And yes, that's another winky face.
I feel like the thread is degenerating into an xkcd cartoon... which isn't necessarily a bad thing. :-) - Daniel

Eric Niebler wrote:
That said, it's an interesting suggestion, and if I can find a light-weight solution, I might float it with the standardization committee and see if there is interest.
Great WG paper by Eric, Daniel and Joel: std::result_of and SFINAE http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3436.html Bravo! Regards, Michel

On 9/30/2012 5:42 AM, Michel Morin wrote:
Eric Niebler wrote:
That said, it's an interesting suggestion, and if I can find a light-weight solution, I might float it with the standardization committee and see if there is interest.
Great WG paper by Eric, Daniel and Joel:
std::result_of and SFINAE http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3436.html
Bravo!
Thanks. I'll be going to Portland to champion the proposal. I expect some wording tweaks, but for it to be otherwise uncontroversial. One wrinkle could be a late proposal by Bjarne and Andrew Sutton to change the rules of sfinae to obviate the need for hacks like this, but I don't think it should effect whether our resolution gets accepted or not. After Portland, I'll post a message here to let folks know how it went. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
Thanks. I'll be going to Portland to champion the proposal. I expect some wording tweaks, but for it to be otherwise uncontroversial. One wrinkle could be a late proposal by Bjarne and Andrew Sutton to change the rules of sfinae to obviate the need for hacks like this, but I don't think it should effect whether our resolution gets accepted or not.
After Portland, I'll post a message here to let folks know how it went.
Looking forward to receiving a positive message ;) This is a bit off-topic, but libstdc++ now implements SFINAE-friendly std::result_of: 2012-10-01 Daniel Krugler * include/std/type_traits (result_of): Provide "SFINAE-friendly" (see N3436) implementation. ( http://gcc.gnu.org/viewcvs?view=revision&revision=191930 ) Regards, Michel

On 9/30/2012 6:03 PM, Eric Niebler wrote:
On 9/30/2012 5:42 AM, Michel Morin wrote:
Eric Niebler wrote:
That said, it's an interesting suggestion, and if I can find a light-weight solution, I might float it with the standardization committee and see if there is interest.
Great WG paper by Eric, Daniel and Joel:
std::result_of and SFINAE http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3436.html
Bravo!
Thanks. I'll be going to Portland to champion the proposal. I expect some wording tweaks, but for it to be otherwise uncontroversial. One wrinkle could be a late proposal by Bjarne and Andrew Sutton to change the rules of sfinae to obviate the need for hacks like this, but I don't think it should effect whether our resolution gets accepted or not.
After Portland, I'll post a message here to let folks know how it went.
Follow up: The paper was accepted. This wording, with minor edits, will be integrated into the working draft and will be part of the next standard (which is slated for 2014, btw). Standard library vendors who haven't implemented it already will probably begin doing so shortly. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
Great WG paper by Eric, Daniel and Joel:
std::result_of and SFINAE http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3436.html
Bravo!
Thanks. I'll be going to Portland to champion the proposal. I expect some wording tweaks, but for it to be otherwise uncontroversial. One wrinkle could be a late proposal by Bjarne and Andrew Sutton to change the rules of sfinae to obviate the need for hacks like this, but I don't think it should effect whether our resolution gets accepted or not.
After Portland, I'll post a message here to let folks know how it went.
Follow up: The paper was accepted. This wording, with minor edits, will be integrated into the working draft and will be part of the next standard (which is slated for 2014, btw).
That's nice, thanks for the follow-up!
Standard library vendors who haven't implemented it already will probably begin doing so shortly.
Now std::result_of and std::common_type are SFINAE-friendly in libstdc++. Regards, Michel

On 9/4/2012 8:01 PM, Joel de Guzman wrote:
The question is: should we allow SFINAE for result_of. I think now that we should.
I made a case for this on the committee reflectors. They generally seem to like the idea. In short: you were right, Joel. I'm now generally in favor of changing result_of. Boost result_of can be existing practice for (hopefully) a future change in the standard. Daniel, is this something you're also interested in? I can see about a patch. Joel, since this is essentially your idea, would you be interested in co-authoring a paper for the committee? I don't anticipate it would have to be very long or elaborate. Also, apologies for my defensiveness earlier. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 9/7/2012 3:37 AM, Eric Niebler wrote:
On 9/4/2012 8:01 PM, Joel de Guzman wrote:
The question is: should we allow SFINAE for result_of. I think now that we should.
I made a case for this on the committee reflectors. They generally seem to like the idea. In short: you were right, Joel. I'm now generally in favor of changing result_of. Boost result_of can be existing practice for (hopefully) a future change in the standard. Daniel, is this something you're also interested in? I can see about a patch.
Joel, since this is essentially your idea, would you be interested in co-authoring a paper for the committee? I don't anticipate it would have to be very long or elaborate.
It'll be an honor to co-author a paper with you.
Also, apologies for my defensiveness earlier.
No need for apologies. I just wanted to say that we need to keep a jovial spirit here in boost. We are all volunteers. We all make mistakes. Apologies for the xkcd-ish comment. Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On Sep 6, 2012, at 8:39 PM, Joel de Guzman wrote:
On 9/7/2012 3:37 AM, Eric Niebler wrote:
On 9/4/2012 8:01 PM, Joel de Guzman wrote:
The question is: should we allow SFINAE for result_of. I think now that we should.
I made a case for this on the committee reflectors. They generally seem to like the idea. In short: you were right, Joel. I'm now generally in favor of changing result_of. Boost result_of can be existing practice for (hopefully) a future change in the standard. Daniel, is this something you're also interested in? I can see about a patch.
Well, I'm not sure what you have in mind, but I went ahead and fleshed out my approach from the other night. I opened a ticket (#7343) and attached a patch. It seems to work pretty well, and the test suite passes. I also added a SFINAE test derived from Joel's example to the test suite. Let me know what you think. As far as the standard, to allow a SFINAE compatible result_of implementation such as the one in my patch you would need language such as the following: If the expression decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...)) is well formed, then the member typedef type shall name the type decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...)). Otherwise, if the expression decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...)) is not well formed, the expression result_of<Fn(ArgTypes...)>::type shall not be well formed. Actually, I'm not sure if the term "well formed" is the right one here, but you get the idea.
Joel, since this is essentially your idea, would you be interested in co-authoring a paper for the committee? I don't anticipate it would have to be very long or elaborate.
It'll be an honor to co-author a paper with you.
Also, apologies for my defensiveness earlier.
No need for apologies. I just wanted to say that we need to keep a jovial spirit here in boost. We are all volunteers. We all make mistakes. Apologies for the xkcd-ish comment.
No need to apologies for xkcd-ish comments. xkcd is brilliant and the world would be a better place if we could all show such good humor and warmth. :-) - Daniel

Daniel Walker wrote:
Well, I'm not sure what you have in mind, but I went ahead and fleshed out my approach from the other night. I opened a ticket (#7343) and attached a patch.
Great work, Daniel! One comment about a patch: I personally used typename boost::remove_reference<decltype(/* INVOKE */)>::type* = 0 rather than boost::mpl::int_<sizeof(/* INVOKE */)>::type* = 0 for `is_callable` metafunction. When the return type of INVOKE is an incomplete type, your `test` returns `fail` regardless of the callability. (The `pass` version of `test` is SFINAE'ed out, since sizeof needs a complete type.) Regards, Michel

On Sep 6, 2012, at 10:41 PM, Michel Morin wrote:
Daniel Walker wrote:
Well, I'm not sure what you have in mind, but I went ahead and fleshed out my approach from the other night. I opened a ticket (#7343) and attached a patch.
Great work, Daniel!
One comment about a patch: I personally used
typename boost::remove_reference<decltype(/* INVOKE */)>::type* = 0
rather than
boost::mpl::int_<sizeof(/* INVOKE */)>::type* = 0
for `is_callable` metafunction.
When the return type of INVOKE is an incomplete type, your `test` returns `fail` regardless of the callability. (The `pass` version of `test` is SFINAE'ed out, since sizeof needs a complete type.)
Excellent catch Michel. :-) Good eyes as always! - Daniel

Eric Niebler wrote:
On 9/4/2012 8:01 PM, Joel de Guzman wrote:
The question is: should we allow SFINAE for result_of. I think now that we should.
I made a case for this on the committee reflectors. They generally seem to like the idea.
Thanks for taking a step forward! [...]
(hopefully) a future change in the standard.
I strongly hope so. Not a small number of people have complained about the disability of std/boost::result_of for SFINAE. Regards, Michel

On Sep 6, 2012, at 10:56 PM, Michel Morin wrote:
Not a small number of people have complained about the disability of std/boost::result_of for SFINAE.
Where has this come up before? I just don't remember. It would be interesting to know the history of this problem. Also, I updated the patch with your suggestion, Michel. Thanks! - Daniel

On 9/7/2012 11:31 AM, Daniel Walker wrote:
On Sep 6, 2012, at 10:56 PM, Michel Morin wrote:
Not a small number of people have complained about the disability of std/boost::result_of for SFINAE.
Where has this come up before? I just don't remember. It would be interesting to know the history of this problem.
The related fusion regression is one: https://svn.boost.org/trac/boost/ticket/6915 and also references a stack-overflow question: http://stackoverflow.com/questions/10632848/boost-fusion-invoke-and-sfinae Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

Daniel Walker wrote:
Not a small number of people have complained about the disability of std/boost::result_of for SFINAE.
Where has this come up before? I just don't remember. It would be interesting to know the history of this problem.
I learned this problem from this blog post: (Note: written in Japanese http://d.hatena.ne.jp/gintenlabo/20110420/1303288950 ) This post listed defects in FDIS. One of them is that some meta-functions (std::result_of and common_type) cannot be used for SFINAE. On gcc bugzilla, Paolo Carlini said the following ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50711 ) Unfortunately, I don't think you can use std::result_of for sfinae purposes, if I understand correctly it's a well know annoyance which you have to overcome by open coding with std::declval. Eg, if you simply open the <functional> header you will find plenty of decltype( std::declval... for sfinae, which cannot be replaced by a concise std::result_of Also, quick google finds an old boost-user ML post: ( http://thread.gmane.org/gmane.comp.lib.boost.user/9967/focus=10030 ) From: Ian McCulloch Subject: Re: result_of tutorial Date: 2005-03-17 08:22:29 GMT Thanks Peter, I think I understand how it works now. Unfortunately, the lack of SFINAE is a real showstopper for me. I want to write functions like template <typename T> typename result_of<negate(T)>::type operator-(T const& x) { return negate()(x); } but the lack of SFINAE here makes boost::result_of essentially useless for this. But I imagine it won't be difficult to make a new version based on boost that would work. Regards, Michel

On Sep 8, 2012, at 12:02 PM, Michel Morin wrote:
Daniel Walker wrote:
Not a small number of people have complained about the disability of std/boost::result_of for SFINAE.
Where has this come up before? I just don't remember. It would be interesting to know the history of this problem.
I learned this problem from this blog post: (Note: written in Japanese http://d.hatena.ne.jp/gintenlabo/20110420/1303288950 ) This post listed defects in FDIS. One of them is that some meta-functions (std::result_of and common_type) cannot be used for SFINAE.
On gcc bugzilla, Paolo Carlini said the following ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50711 )
Unfortunately, I don't think you can use std::result_of for sfinae purposes, if I understand correctly it's a well know annoyance which you have to overcome by open coding with std::declval.
Eg, if you simply open the <functional> header you will find plenty of decltype( std::declval... for sfinae, which cannot be replaced by a concise std::result_of
Ah, that makes sense. I guess it's not surprising that this would be a well know problem to std lib implementers.
Also, quick google finds an old boost-user ML post: ( http://thread.gmane.org/gmane.comp.lib.boost.user/9967/focus=10030 )
From: Ian McCulloch Subject: Re: result_of tutorial Date: 2005-03-17 08:22:29 GMT
Thanks Peter, I think I understand how it works now. Unfortunately, the lack of SFINAE is a real showstopper for me. I want to write functions like
template <typename T> typename result_of<negate(T)>::type operator-(T const& x) { return negate()(x); }
but the lack of SFINAE here makes boost::result_of essentially useless for this. But I imagine it won't be difficult to make a new version based on boost that would work.
I'm going to add a comment to the patch with a pointer to this thread in case someone in the future is interested in the history of the problem. Nice scholarship. Do you know of any previously proposed solutions to the SFINAE problem; e.g. alternative result_of implementations? - Daniel

Daniel Walker wrote:
Do you know of any previously proposed solutions to the SFINAE problem; e.g. alternative result_of implementations?
This post (Note: written in Japanese http://d.hatena.ne.jp/iorate/20110717/1310913102 ) says that boost::result_of (and std::result_of) cannot be used for SFINAE and presents the following implementation template < class , class = void > struct result_of_aux {}; template < class F, class ...Args> struct result_of_aux<F(Args...), decltype(std::declval<F>()(std::declval<Args>()...), void ())> { typedef decltype(std::declval<F>()(std::declval<Args>()...)) type; }; template < class Sig> struct result_of : result_of_aux<Sig> {}; Regards, Michel

On 9/8/2012 12:45 PM, Michel Morin wrote:
template < class , class = void > struct result_of_aux {};
template < class F, class ...Args> struct result_of_aux<F(Args...), decltype(std::declval<F>()(std::declval<Args>()...), void ())> { typedef decltype(std::declval<F>()(std::declval<Args>()...)) type; };
What is void()? That's not any expression I recognize. It's a function type. Anyway, keep in mind that std::declval<F>()(...) could have an incomplete type, so you can't really use it in an expression. You should use it in decltype, and then pass it as a template parameter to something like this: template<typename T> struct always_void { typedef void type; }; template < class , class = void > struct result_of_aux {}; template < class F, class ...Args> struct result_of_aux<F(Args...), typename always_void<decltype(std::declval<F>()(std::declval<Args>()...))>::type> { typedef decltype(std::declval<F>()(std::declval<Args>()...)) type; }; HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
template < class , class = void > struct result_of_aux {};
template < class F, class ...Args> struct result_of_aux<F(Args...), decltype(std::declval<F>()(std::declval<Args>()...), void ())> { typedef decltype(std::declval<F>()(std::declval<Args>()...)) type; };
What is void()? That's not any expression I recognize. It's a function type.
5.2.3 [expr.type.conv] p2 The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv -qualified) void type, creates a prvalue of the specified type, which is value-initialized ( 8.5; no initialization is done for the void() case).
Anyway, keep in mind that std::declval<F>()(...) could have an incomplete type, so you can't really use it in an expression. You should use it in decltype,
All the use of `std::declval<F>()(...)` is in decltype and so I don't see any problem in the code. Do you mean struct result_of_aux< F(Args...) , decltype(std::declval<F>()(std::declval<Args>()...), void ()) > can be a hard error? Regards, Michel

On 9/10/2012 5:05 AM, Michel Morin wrote:
Eric Niebler wrote:
template < class , class = void > struct result_of_aux {};
template < class F, class ...Args> struct result_of_aux<F(Args...), decltype(std::declval<F>()(std::declval<Args>()...), void ())> { typedef decltype(std::declval<F>()(std::declval<Args>()...)) type; };
What is void()? That's not any expression I recognize. It's a function type.
5.2.3 [expr.type.conv] p2 The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv -qualified) void type, creates a prvalue of the specified type, which is value-initialized ( 8.5; no initialization is done for the void() case).
A prvalue of type void? That's whack.
Anyway, keep in mind that std::declval<F>()(...) could have an incomplete type, so you can't really use it in an expression. You should use it in decltype,
All the use of `std::declval<F>()(...)` is in decltype and so I don't see any problem in the code. Do you mean struct result_of_aux< F(Args...) , decltype(std::declval<F>()(std::declval<Args>()...), void ()) > can be a hard error?
Yes indeedy. struct X; X foo(); typedef decltype(foo()) Y; // OK typedef decltype(foo(), void()) Z; // ERROR -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
All the use of `std::declval<F>()(...)` is in decltype and so I don't see any problem in the code. Do you mean struct result_of_aux< F(Args...) , decltype(std::declval<F>()(std::declval<Args>()...), void ()) > can be a hard error?
Yes indeedy.
struct X; X foo();
typedef decltype(foo()) Y; // OK typedef decltype(foo(), void()) Z; // ERROR
Ah yes, it indeed produces an error. Thanks! Regards, Michel

On Sep 1, 2012, at 8:12 PM, Joel de Guzman wrote:
On 9/2/12 7:24 AM, Eric Niebler wrote:
We will have to make a very BOLD announcement in the release notes of 1.52. Not only will users of Phoenix be affected; anybody who relies on boost::result_of to use the TR1 protocol will be broken by this. This might be a painful transition for some, but there's no helping that.
I have no problem with this as long as there's clear documentation on what users would expect and how to deal with them in their code.
Below is a first stab at documenting breaking changes for the release notes and/or result_of documentation. Is there anything I'm missing? Any caveats regarding N3276? Is this too much? Too little? BREAKING CHANGES TO BOOST RESULT_OF On compilers that adequately implement C++11 decltype (clang 3.1, gcc 4.7, Visual C++ 11), result_of now uses decltype by default to deduce return types rather than following the TR1 result_of protocol, which is no longer required. While this makes result_of much more useful, it also necessitates new behaviors which will break some existing code. The following are use-cases where result_of behaves differently depending on whether decltype is used. The macro BOOST_RESULT_OF_USE_DECLTYPE is defined when result_of is using decltype. Please see the result_of documentation for more information. 1) TR1 protocol misusage When using the TR1 protocol, result_of cannot tell whether the actual type of a call to a function object is the same as the type specified by the protocol, which allows for the possibility of inadvertent mismatches between the specified type and the actual type. When using decltype, these subtle bugs will be detected and may result in compilation errors. struct functor { typedef short result_type; int operator()(short); }; #ifdef BOOST_RESULT_OF_USE_DECLTYPE BOOST_STATIC_ASSERT(( is_same<result_of<functor(short)>::type, int>::value )); #else BOOST_STATIC_ASSERT(( is_same<result_of<functor(short)>::type, short>::value )); #endif 2) Nullary function objects When using the TR1 protocol, result_of cannot always deduce the type of calls to nullary function objects, in which case the type defaults to void. When using decltype, result_of always gives the actual type of the call expression. Example: struct functor { template<class> struct result { typedef int type; }; int operator()(); }; #ifdef BOOST_RESULT_OF_USE_DECLTYPE BOOST_STATIC_ASSERT(( is_same<result_of<functor()>::type, int>::value )); #else BOOST_STATIC_ASSERT(( is_same<result_of<functor()>::type, void>::value )); #endif 3) Non-class prvalues and cv-qualification When using the TR1 protocol, result_of will report the cv-qualified type specified by the result_type or result<> members, regardless of the actual cv-qualification of the call expression. When using decltype, result_of will report the actual type of the call expression, which is not cv-qualified when the expression is a non-class prvalue. Example: struct functor { template<class> struct result; template<class F, class T> struct result<F(const T)> { typedef const T type; }; const short operator()(const short); int const & operator()(int const &); }; // Non-prvalue call expressions work the same with or without decltype. BOOST_STATIC_ASSERT(( is_same< result_of<functor(int const &)>::type, int const & >::value )); // Non-class prvalue call expressions are not actually cv-qualified, // but only the decltype-based result_of reports this accurately. #ifdef BOOST_RESULT_OF_USE_DECLTYPE BOOST_STATIC_ASSERT(( is_same< result_of<functor(const short)>::type, short >::value )); #else BOOST_STATIC_ASSERT(( is_same< result_of<functor(const short)>::type, const short >::value )); #endif - Daniel

(Apologies for the top-post. I'm on the road.) This looks good, thanks Daniel. Suggestions; don't say the TR1 protocol is "no longer required." It *is* required if you want your function objects to be portable to older compilers. I also don't know what you mean by "necessitates new behaviors". By or from whom? By and large, if people have been doing it right all along, they should be ok. We might also point out that the idiom of specializing boost::result_of to get the right answer for nullary function objects is no longer required, and should be conditioned on BOOST_RESULT_OF_USE_DECLTYPE. Thanks for doing this, Eric Sent via tiny mobile device -----Original Message----- From: Daniel Walker <daniel.j.walker@gmail.com> Date: Mon, 3 Sep 2012 14:16:17 To: Joel de Guzman<joel@boostpro.com> Cc: Eric Niebler<eric@boostpro.com>; <boost@lists.boost.org>; Michel Morin<mimomorin@gmail.com>; Thomas Heller<thom.heller@gmail.com> Subject: Re: [result_of] now uses decltype on release branch On Sep 1, 2012, at 8:12 PM, Joel de Guzman wrote:
On 9/2/12 7:24 AM, Eric Niebler wrote:
We will have to make a very BOLD announcement in the release notes of 1.52. Not only will users of Phoenix be affected; anybody who relies on boost::result_of to use the TR1 protocol will be broken by this. This might be a painful transition for some, but there's no helping that.
I have no problem with this as long as there's clear documentation on what users would expect and how to deal with them in their code.
Below is a first stab at documenting breaking changes for the release notes and/or result_of documentation. Is there anything I'm missing? Any caveats regarding N3276? Is this too much? Too little? BREAKING CHANGES TO BOOST RESULT_OF On compilers that adequately implement C++11 decltype (clang 3.1, gcc 4.7, Visual C++ 11), result_of now uses decltype by default to deduce return types rather than following the TR1 result_of protocol, which is no longer required. While this makes result_of much more useful, it also necessitates new behaviors which will break some existing code. The following are use-cases where result_of behaves differently depending on whether decltype is used. The macro BOOST_RESULT_OF_USE_DECLTYPE is defined when result_of is using decltype. Please see the result_of documentation for more information. 1) TR1 protocol misusage When using the TR1 protocol, result_of cannot tell whether the actual type of a call to a function object is the same as the type specified by the protocol, which allows for the possibility of inadvertent mismatches between the specified type and the actual type. When using decltype, these subtle bugs will be detected and may result in compilation errors. struct functor { typedef short result_type; int operator()(short); }; #ifdef BOOST_RESULT_OF_USE_DECLTYPE BOOST_STATIC_ASSERT(( is_same<result_of<functor(short)>::type, int>::value )); #else BOOST_STATIC_ASSERT(( is_same<result_of<functor(short)>::type, short>::value )); #endif 2) Nullary function objects When using the TR1 protocol, result_of cannot always deduce the type of calls to nullary function objects, in which case the type defaults to void. When using decltype, result_of always gives the actual type of the call expression. Example: struct functor { template<class> struct result { typedef int type; }; int operator()(); }; #ifdef BOOST_RESULT_OF_USE_DECLTYPE BOOST_STATIC_ASSERT(( is_same<result_of<functor()>::type, int>::value )); #else BOOST_STATIC_ASSERT(( is_same<result_of<functor()>::type, void>::value )); #endif 3) Non-class prvalues and cv-qualification When using the TR1 protocol, result_of will report the cv-qualified type specified by the result_type or result<> members, regardless of the actual cv-qualification of the call expression. When using decltype, result_of will report the actual type of the call expression, which is not cv-qualified when the expression is a non-class prvalue. Example: struct functor { template<class> struct result; template<class F, class T> struct result<F(const T)> { typedef const T type; }; const short operator()(const short); int const & operator()(int const &); }; // Non-prvalue call expressions work the same with or without decltype. BOOST_STATIC_ASSERT(( is_same< result_of<functor(int const &)>::type, int const & >::value )); // Non-class prvalue call expressions are not actually cv-qualified, // but only the decltype-based result_of reports this accurately. #ifdef BOOST_RESULT_OF_USE_DECLTYPE BOOST_STATIC_ASSERT(( is_same< result_of<functor(const short)>::type, short >::value )); #else BOOST_STATIC_ASSERT(( is_same< result_of<functor(const short)>::type, const short >::value )); #endif - Daniel

<eric@boostpro.com> wrote:
We might also point out that the idiom of specializing boost::result_of to get the right answer for nullary function objects is no longer required, and should be conditioned on BOOST_RESULT_OF_USE_DECLTYPE.
And another consequence of this change is that the following code breaks with decltype-based result_of for a non-nullary function object F template <typename F> struct FuncWrapper { typename boost::result_of<F()>::type operator()(); /* ... */ }; as described in [Part 2 of 3] of my reply to Daniel. Regards, Michel

On Sep 3, 2012, at 3:08 PM, eric@boostpro.com wrote:
This looks good, thanks Daniel. Suggestions; don't say the TR1 protocol is "no longer required." It *is* required if you want your function objects to be portable to older compilers. I also don't know what you mean by "necessitates new behaviors". By or from whom? By and large, if people have been doing it right all along, they should be ok.
We might also point out that the idiom of specializing boost::result_of to get the right answer for nullary function objects is no longer required, and should be conditioned on BOOST_RESULT_OF_USE_DECLTYPE.
Thanks for the feedback. I incorporated this into a new section of the result_of documentation for known differences between decltype-based result_of and the TR1 protocol. The release notes could now simply refer readers to this section for more info. Something like.. BREAKING CHANGES TO BOOST RESULT_OF On compilers that adequately implement C++11 decltype (clang 3.1, Visual C++ 11), boost::result_of now uses decltype by default rather than following the TR1 result_of protocol. We anticipate that most users will not notice a change. However, in some situations migrating from the TR1 protocol to decltype may cause breaking changes. Users can force boost::result_of to continue to follow the TR1 protocol by defining BOOST_RESULT_OF_USE_TR1. For more information about differences between decltype-based result_of and the TR1 protocol see the documentation at http://www.boost.org/doc/libs/1_52_0/libs/utility/utility.htm#result_of_tr1_.... - Daniel

On compilers that adequately implement C++11 decltype (clang 3.1, gcc 4.7, Visual C++ 11)
Does GCC 4.7 adequately implement decltype? I seem to recall some discussion of compilers not adequately implementing decltype by virtue of not supporting the extensions specified nN3276 [1]. As far as I'm aware, gcc 4.7 has not implemented these extensions yet [2]. Regards,Nate [1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf[2] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52748

On Sep 3, 2012, at 6:58 PM, Nathan Ridge wrote:
On compilers that adequately implement C++11 decltype (clang 3.1, gcc 4.7, Visual C++ 11)
Does GCC 4.7 adequately implement decltype? I seem to recall some discussion of compilers not adequately implementing decltype by virtue of not supporting the extensions specified nN3276 [1]. As far as I'm aware, gcc 4.7 has not implemented these extensions yet [2]. Regards,Nate [1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf[2] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52748
Thanks Nate. For the 1.52 release notes, will someone have a list of compilers for which decltype result_of is enabled by default? When is the release by the way? - Daniel

Daniel Walker wrote:
For the 1.52 release notes, will someone have a list of compilers for which decltype result_of is enabled by default?
Clang-3.1 (and trunk) in a C++11 mode and, expectedly, VC++11. (Note that VC++ config change is not committed yet.) VC++11 does not have a C++03/C++11 compiler switch and it always runs in a C++11 mode.
When is the release by the way?
According to http://www.boost.org/community/index.html , Sep 17: 1.52.0 Closed for new libs and breaking changes. Nov 5: 1.52.0 Release. Regards, Michel

On Sep 3, 2012, at 7:37 PM, Michel Morin wrote:
Daniel Walker wrote:
For the 1.52 release notes, will someone have a list of compilers for which decltype result_of is enabled by default?
Clang-3.1 (and trunk) in a C++11 mode and, expectedly, VC++11. (Note that VC++ config change is not committed yet.) VC++11 does not have a C++03/C++11 compiler switch and it always runs in a C++11 mode.
When is the release by the way?
According to http://www.boost.org/community/index.html , Sep 17: 1.52.0 Closed for new libs and breaking changes. Nov 5: 1.52.0 Release.
OK, so clang 3.1 will be on the list (in C++11 mode). N3276 is a necessary condition for turning on decltype-based result_of by default. It seems unlikely that gcc would introduce support by Sep 17, but I'm not following their develop schedule at all. I think it's OK if clang and (presumably) msvc are the only compilers that get the change this time around. If someone finds out more about gcc's progress, please let the list know. - Daniel

Nathan Ridge wrote:
On compilers that adequately implement C++11 decltype (clang 3.1, gcc 4.7, Visual C++ 11)
Does GCC 4.7 adequately implement decltype? I seem to recall some discussion of compilers not adequately implementing decltype by virtue of not supporting the extensions specified nN3276 [1]. As far as I'm aware, gcc 4.7 has not implemented these extensions yet [2].
Right. gcc-4.7 does not implement N3276 decltype, though it implements "3) Non-class prvalues and cv-qualification" (which was proposed later than N3276). Regards, Michel

Daniel Walker wrote:
Below is a first stab at documenting breaking changes for the release notes and/or result_of documentation.
Great, Daniel! Here are some comments to the release notes and general discussions. (My comments might be too detailed and not good for the release notes.) [Part 1 of 3]
BREAKING CHANGES TO BOOST RESULT_OF
[...] The macro BOOST_RESULT_OF_USE_DECLTYPE is defined when result_of is using decltype. Please see the result_of documentation for more information.
Better to mention BOOST_RESULT_OF_USE_TR1 to force TR1-style result_of?
1) TR1 protocol misusage [...] #ifdef BOOST_RESULT_OF_USE_DECLTYPE [...]
Should be !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) One can define BOOST_RESULT_OF_USE_DECLTYPE on compilers without decltype support and, in that case, TR1-style result_of is used. This is the behavior of the macro. Once Eric changed this, but I claimed the regression and the change was reverted ( http://thread.gmane.org/gmane.comp.lib.boost.devel/230401/ ). In that thread, I might have over-emphasized the regression. If you think the effect of the code breakage is small enough, then I think it's OK to reapply Eric's change. Regards, Michel

On Sep 3, 2012, at 11:20 PM, Michel Morin wrote:
One can define BOOST_RESULT_OF_USE_DECLTYPE on compilers without decltype support and, in that case, TR1-style result_of is used. This is the behavior of the macro.
Once Eric changed this, but I claimed the regression and the change was reverted ( http://thread.gmane.org/gmane.comp.lib.boost.devel/230401/ ). In that thread, I might have over-emphasized the regression. If you think the effect of the code breakage is small enough, then I think it's OK to reapply Eric's change.
I followed this thread at the time. It seemed like you guys came to a reasonable resolution so I felt no need to comment. However, now that I'm going over the documentation again I'm having second thoughts. The documentation actually states that BOOST_RESULT_OF_USE_DECLTYPE can be used to force the use of decltype. As Nathan and others pointed out at the time, forcing the use of decltype on a compiler that doesn't have it can be viewed as a logical error, which is probably the right way to look at it. I think Eric's original change was correct and should be reapplied. - Daniel

Daniel Walker wrote:
The documentation actually states that BOOST_RESULT_OF_USE_DECLTYPE can be used to force the use of decltype.
That's simply because the doc change was not reverted ;)
I think Eric's original change was correct and should be reapplied.
Yes, with release notes! Regards, Michel

[Part 2 of 3] Daniel Walker wrote:
2) Nullary function objects [...] struct functor { template<class> struct result { typedef int type; }; int operator()(); };
There are two types of misusage of result_of: A. Wrong definition of return types B. Return type evaluation with uncallable signatures I think the above code (i.e. the code with nullary function objects that do not specialize boost::result_of/tr1_result_of class template) belongs to A. The consequence of "TR1-style result_of has the default type `void` for nullary calls" is related to B. B is allowed with TR1-style result_of in many cases, since * Callability is not checked for function pointers. * Callability is not checked for function objects having `result_type`. * Nested class template `result` is often partially specialized (in a way that uncallable signatures are allowed). * Nullary calls are always allowed. With decltype-based result_of, B is not allowed at all. TR1-style result_of has the default type `void` to allow template <typename F> struct FuncWrapper { typename boost::result_of<F()>::type operator()(); /* ... */ }; for function objects that are not nullary-callable. But, with decltype-based result_of, this code fails to compile for non-nullary function objects. I think this is an important breaking change. We can avoid compiler errors using variadic templates. But, IIRC, VC++ 11 does not implement variadic templates. Regards, Michel

[Part 3 of 3] Daniel Walker wrote:
3) Non-class prvalues and cv-qualification
Since this C++11 behavior was proposed later than N3276, it's possible that there is a non-C++11-compliant compiler that implements N3276 but not (3). Would it be better to emulate (3) when using decltype-based result_of? But then boost::result_of returns different results than those of std::result_of on compilers that do not implement (3). Regards, Michel

Here is a list of test failures due to decltype-based result_of. (Note: this list is a bit old. Tests were done for trunk four months ago.) Michel Morin wrote:
libs/functional/forward/test/forward_adapter.test libs/functional/forward/test/lightweight_forward_adapter.test libs/fusion/test/invoke.test libs/phoenix/test/bind_not_test.test libs/phoenix/test/bind_rv_sp_test.test libs/phoenix/test/bind_stateful_test.test libs/phoenix/test/bind_test.test libs/phoenix/test/bug3289.test libs/phoenix/test/dynamic_tests.test libs/phoenix/test/exceptions.test libs/phoenix/test/if_tests.test libs/phoenix/test/lambda_tests.test libs/phoenix/test/loops_tests.test libs/phoenix/test/member.test libs/phoenix/test/new_delete_tests.test libs/phoenix/test/switch_tests.test libs/spirit/repository/test/qi_repo_advance.test libs/spirit/repository/test/qi_repo_keywords.test libs/spirit/test/lex_regression_file_iterator3-p3.test libs/utility/test/result_of_test.test
And here is the current situation: [Functional/Forward] Not fixed. Patch attached by Eric Niebler. https://svn.boost.org/trac/boost/ticket/6828 [Fusion] Not fixed. [Phoenix] Not fixed. https://svn.boost.org/trac/boost/ticket/5687 [Spirit] ??? [result_of] Fixed recently by Daniel Walker. https://svn.boost.org/trac/boost/ticket/6754 Regards, Michel

[Michel Morin]
For a function `const int f()`, `decltype(f())` returns `int` on VC++ 11. So some `result_of` tests fail as in #6754. ( https://svn.boost.org/trac/boost/ticket/6754 ) Clang 3.1 and gcc 4.7-4.8 behaves similarly, and this behavior conforms to the C++11 Standard.
I'm confused, because I observe this with VC11 RTM: C:\Temp>type meow.cpp #include <stdio.h> template <typename T> struct Print; template <> struct Print<int> { static void print() { puts("int"); } }; template <> struct Print<const int> { static void print() { puts("const int"); } }; const int f() { return 1729; } int main() { printf("%02d.%02d.%05d.%02d\n", _MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 100000, _MSC_BUILD); Print<decltype(f())>::print(); } C:\Temp>cl /EHsc /nologo /W4 /MTd meow.cpp meow.cpp C:\Temp>meow 17.00.50727.01 const int I see N3376 3.10 [basic.lval]/4 "Class prvalues can have cv-qualified types; non-class prvalues always have cv-unqualified types." so I am quite willing to believe that "int" is the correct answer here, but before I file a compiler bug I'd like to verify what's going on here. Thanks, STL

Stephan T. Lavavej wrote:
[Michel Morin]
For a function `const int f()`, `decltype(f())` returns `int` on VC++ 11. So some `result_of` tests fail as in #6754. ( https://svn.boost.org/trac/boost/ticket/6754 ) Clang 3.1 and gcc 4.7-4.8 behaves similarly, and this behavior conforms to the C++11 Standard.
I'm confused, because I observe this with VC11 RTM:
const int f() { return 1729; }
int main() { Print<decltype(f())>::print(); }
C:\Temp>meow const int
(I rearranged the code above for readability.) Thanks for pointing this out, Stephan. It's highly possible that I did a wrong test. (I usually use cvref-preserving type-name printer. But, when I used VC++ 11, I think I used typeid + name() for getting the type-name.) So, "For a function `const int f()`, `decltype(f())` returns `int` on VC++ 11." is wrong. VC++11 implements N3276 decltype, but not FDIS decltype. Sorry for the confusion. Regards, Michel

[Michel Morin]
Thanks for pointing this out, Stephan. It's highly possible that I did a wrong test. (I usually use cvref-preserving type-name printer. But, when I used VC++ 11, I think I used typeid + name() for getting the type-name.)
Thanks, I just wanted to make sure that nothing really crazy was happening. I've filed DevDiv#483634 "Given const int f(), decltype(f()) should be int" in our internal database for our compiler team to look at, with the magic words "it affects std::result_of and boost::result_of". STL

This bug has been fixed in VC12. Thanks again! STL -----Original Message----- From: Stephan T. Lavavej Sent: Monday, September 10, 2012 6:42 PM To: boost@lists.boost.org Subject: RE: [boost] [Config] N3276 decltype support on VC++ 11 [Michel Morin]
Thanks for pointing this out, Stephan. It's highly possible that I did a wrong test. (I usually use cvref-preserving type-name printer. But, when I used VC++ 11, I think I used typeid + name() for getting the type-name.)
Thanks, I just wanted to make sure that nothing really crazy was happening. I've filed DevDiv#483634 "Given const int f(), decltype(f()) should be int" in our internal database for our compiler team to look at, with the magic words "it affects std::result_of and boost::result_of". STL

Stephan T. Lavavej wrote:
I've filed DevDiv#483634 "Given const int f(), decltype(f()) should be int" in our internal database for our compiler team to look at, with the magic words "it affects std::result_of and boost::result_of".
This bug has been fixed in VC12.
Nice :) I'm also looking forward to seeing another decltype bug decltype fails in recursive function object scenario https://connect.microsoft.com/VisualStudio/feedback/details/764260/ which is found by Eric [config] msvc-11 and BOOST_NO_CXX11_DECLTYPE_N3276 http://thread.gmane.org/gmane.comp.lib.boost.devel/234483/ will be fixed. Oh..., that's already fixed: Posted by Microsoft on 2/6/2013 at 1:35 PM [...] it has been fixed. The fix should show up in tyhe next release of Visual C++. Great! So, there is no blocker that prevents from enabling decltype-based result_of by default on VC++12. Regards, Michel

On Aug 31, 2012, at 10:04 AM, Michel Morin <mimomorin@gmail.com> wrote:
IIRC, Stephan said that VC++ 11 supports N3276 decltype.
Shall we "undef" BOOST_NO_CXX11_DECLTYPE_N3276 for VC++ 11? This enables automatic use of decltype-based `boost::result_of`. Trivial patch attached.
What we need to do is to figure out the differences between VC10 and VC11 and update the VC config for that. This is one part of it (thanks!) -- Marshall Marshall Clow Idio Software <mailto:mclow.lists@gmail.com> A.D. 1517: Martin Luther nails his 95 Theses to the church door and is promptly moderated down to (-1, Flamebait). -- Yu Suzuki

[Michel Morin]
IIRC, Stephan said that VC++ 11 supports N3276 decltype.
Yep. [Marshall Clow]
What we need to do is to figure out the differences between VC10 and VC11 and update the VC config for that.
http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx is the Rosetta Stone - it is accurate to the best of my ability. There is one caveat - rvalue references v2.1 was not completely implemented (it is still tracked by an active bug). This demonstrates what works and what doesn't: C:\Temp>type meow.cpp #include <stdio.h> #include <string> using namespace std; void foo(const string&) { puts("foo(const string&)"); } void foo(string&&) { puts("foo(string&&)"); } #ifdef BAR void bar(long&&) { puts("bar(long&&)"); } #endif int main() { foo("meow"); #ifdef BAR int x = 1729; bar(x); #endif } C:\Temp>cl /EHsc /nologo /W4 /MTd meow.cpp meow.cpp C:\Temp>meow foo(string&&) C:\Temp>cl /EHsc /nologo /W4 /MTd /DBAR meow.cpp meow.cpp meow.cpp(24) : error C2664: 'bar' : cannot convert parameter 1 from 'int' to 'long &&' You cannot bind an lvalue to an rvalue reference C++11 and VC11 agree that foo(string&&) should be selected (the string literal is an lvalue, but the temporary std::string is an rvalue). C++11 says that bar(long&&) should be invoked (int x is an lvalue, but the temporary long is an rvalue), but VC11 rejects this. That's the remaining bug. Hope this helps, STL

Stephan T. Lavavej wrote:
[Michel Morin]
IIRC, Stephan said that VC++ 11 supports N3276 decltype.
Yep.
Thanks!
[Marshall Clow]
What we need to do is to figure out the differences between VC10 and VC11 and update the VC config for that.
http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx is the Rosetta Stone - it is accurate to the best of my ability. There is one caveat - rvalue references v2.1 was not completely implemented (it is still tracked by an active bug).
OK, what is missing in Boost.Config for VC++ 11 is only about N3276 decltype support. Regards, Michel

Michel Morin wrote:
IIRC, Stephan said that VC++ 11 supports N3276 decltype.
Shall we "undef" BOOST_NO_CXX11_DECLTYPE_N3276 for VC++ 11? This enables automatic use of decltype-based `boost::result_of`. Trivial patch attached.
John, I know you are busy now. So I'll commit this patch. (Stephan already confirmed that VC++11 supports N3276 decltype.) Regards, Michel

Michel Morin wrote:
IIRC, Stephan said that VC++ 11 supports N3276 decltype.
Shall we "undef" BOOST_NO_CXX11_DECLTYPE_N3276 for VC++ 11? This enables automatic use of decltype-based `boost::result_of`. Trivial patch attached.
John, I know you are busy now. So I'll commit this patch. (Stephan already confirmed that VC++11 supports N3276 decltype.)
Thanks, have been blissfully email and computer free for week ;-) John.
participants (11)
-
Daniel Walker
-
Eric Niebler
-
eric@boostpro.com
-
Jeffrey Lee Hellrung, Jr.
-
Joel de Guzman
-
Joel de Guzman
-
John Maddock
-
Marshall Clow
-
Michel Morin
-
Nathan Ridge
-
Stephan T. Lavavej