Boost logo

Boost :

Subject: Re: [boost] [result_of] now uses decltype on release branch
From: Joel de Guzman (djowel_at_[hidden])
Date: 2012-09-04 22:56:23


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_at_[hidden]> 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_at_[hidden]> 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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk