
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