On Thu, Nov 29, 2012 at 8:29 AM, Eric Niebler <eric@boostpro.com> wrote:
On 11/28/2012 10:37 PM, Jeffrey Lee Hellrung, Jr. wrote:
> On Wed, Nov 28, 2012 at 10:26 PM, Eric Niebler wrote:
>>
>> On 11/22/2012 11:31 AM, Jeffrey Lee Hellrung, Jr. wrote:
>>> Maybe this is what you did, so I might not be suggesting something
>>> new,
>>> but... Perhaps boost::result_of could have an extra conditional logic
>>> branch added to it:
>>> - If F::result_type exists, return F::result_type;
>>> - Else:
>>>   - If BOOST_NO_CXX11_DECLTYPE, return F::result< F ( Args... ) >
>>>   - Else, if F::result<> exists, return F::result< F ( Args... ) >
>>>   - Else return decltype( declval<F>() ( declval< Args >()... ) )
>>
>>     C++11 defines exactly what result_of does, as did the TR1 spec before
>>     it. Making boost::result_of do something different would be
>>     surprising, IMO.
>>
>>     If you want to use C++11 lambdas with boost::result_of, the most
>>     portable solution is with an adapter, as has been suggested elsewhere in
>>     this thread. Not ideal, but it works.
>
>
> I'm only suggesting to extend result_of for C++11 lambdas (and,
> incidentally, other callable types) when result_of wouldn't know what to
> do otherwise. Do you mean it would be surprising for result_of to work
> when it would be expected to fail? Maybe there's something subtle I'm
> missing here.
>
> I'm supposing in this, of course, that there are compilers which support
> lambdas and have some form of decltype sufficient for lambdas but
> insufficient to be the primary implementation of result_of (i.e., must
> use TR1-style for the primary implementation). That's quite a few
> compilers presently, right?

Here's the surprising part:

> - If F::result_type exists, return F::result_type;
> - Else:
>    - If BOOST_NO_CXX11_DECLTYPE, return F::result< F ( Args... ) >
>    - Else, if F::result<> exists, return F::result< F ( Args... ) >
>    - Else return decltype( declval<F>() ( declval< Args >()... ) )

The way I read this is that F::result_type (and F::result<>) is taking
precedence over decltype. AFAICT, you're suggesting that result_of *not*
compute the actual return type of a function object, but rather return
the declared result type, even if it's wrong.

In moving to a decltype-based result_of, we discovered just how many
function objects in boost were lying about their return types via the
TR1 result_of protocol. Now that we have decltype, we can get the right
answer always. I would be *immensely* surprised if result_of ever got
the wrong answer on a compiler that had decltype.

AFAIK, this is the situation we already have: many compilers have decltype but not in sufficient capacity to reliably use in the implementation of result_of. I thought you were one of the individuals spear-heading this distinction :)

I think this is where we're not on the same page: I'm not proposing any changes to result_of in the event that use of decltype is enabled (either because a capable decltype is detected or via a configuration macro). Rather, I am proposing changes to result_of in the event that some form of decltype exists but result_of is still using the TR1-style protocol (i.e., using F::result_type or F::result<>). And, to reiterate, the latter situation, I had thought, was rather prevalent.

And btw, I don't think lambdas are required to have a nested result_type
typedef, are they? So what benefit does changing the protocol have?
Wouldn't you still need a wrapper anyway?

You would if there's no decltype whatsoever. I'm guessing there are few compilers that have lambdas but lack any form of decltype, but that's less relevant than the number of compilers that have, lambdas, have some form of decltype, but nonetheless don't use decltype in result_of.

- Jeff