[Range & c++0x Lambdas] Can this be done?

classic Classic list List threaded Threaded
31 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Re: [Range & c++0x Lambdas] Can this be done?

Nate Crookston

Eric Niebler wrote:
Here's the surprising part:

Jeffrey Lee Hellrung, Jr. wrote:
> - 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.
 
I understood the suggestion to apply when compilers had pre-3276 decltype -- so the above wouldn't apply to latest clang, nor to other compilers once they support incomplete types.
 
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?
 No, they're not required.  That's the heart of the issue -- if result_of were modified (only for lacking compilers) to fall back to decltype, then the lack of result_type wouldn't require special handling by the user.

Thanks,
Nate


_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Range & c++0x Lambdas] Can this be done?

Jeffrey Lee Hellrung, Jr.-2
In reply to this post by Eric Niebler-3
On Thu, Nov 29, 2012 at 8:29 AM, Eric Niebler <[hidden email]> 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


_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Range & c++0x Lambdas] Can this be done?

Jeffrey Lee Hellrung, Jr.-2
In reply to this post by Nate Crookston
On Thu, Nov 29, 2012 at 12:19 AM, Nathan Crookston <[hidden email]> wrote:
Jeff,

Jeffrey Lee Hellrung, Jr. wrote:
Nathan Crookston wrote:
1. Both this and Michel's suggestions require C++11 features -- either decltype or rvalue references.  Extended transformed allows the creation of a result_binder struct to be delayed until the reference type of the input range is available.  This would make it usable for non-lambda instances where an explicit return type is desired without the fuss of defining a separate functor (assuming the functor to be wrapped cannot be changed).  I believe a correct C++03 version of result_binder would need a large number of operator() overloads depending on how many arguments it intends to forward.

True, though this sounds like more of an implementation concern (don't get me wrong, it's a valid concern) than a capability concern.
Agreed.  I think there's also slightly more mental drag involved with a result_binder call, especially if I also need to remember where it resides to #include it.  But that's minor.

That's a legitimate point as well.
 

2. Such a syntax (transformed<R>(...)) has been used previously -- boost bind's docs, referring to bind<R> syntax, state:  "It is generally used with function objects that do not, or cannot, expose result_type."[1]  Without begging for an Emerson quote, I believe consistency with bind in this case will improve the usability enough to justify the required changes.  Note also that this is the only current adaptor[2] which takes a function object with arbitrary return type (others must return something which is convertible to bool).  Note also that the changes are a pure extension (previous usage continues unchanged).

I'm personally not swayed but it's a fair rationale nonetheless and ultimately your call since I'm not doing it :)
I've done all I plan to, unless a maintainer decides it's worth using and would like some changes.  Just to be clear, Nathan Ridge has been proposed as a sub-maintainer, not myself.  (FWIW, I think he's an excellent choice for that position.)

Yeah, I was confused about who was who, sorry :/

Sorry, this probably came earlier in the thread, but I suppose you have a ticket + patch lying around somewhere? Or has a Boost.Range maintainer agreed to implement these changes?

- Jeff


_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Range & c++0x Lambdas] Can this be done?

Eric Niebler-3
In reply to this post by Nate Crookston
On 11/29/2012 9:29 AM, Nathan Crookston wrote:

> Eric Niebler wrote:
>> Here's the surprising part:
>>
>> Jeffrey Lee Hellrung, Jr. wrote:
>>> - 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.
>
> I understood the suggestion to apply when compilers had pre-3276
> decltype -- so the above wouldn't apply to latest clang, nor to
> other compilers once they support incomplete types.

Ah. Forgive me for having misunderstood the suggestion.

>> 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?
>
> No, they're not required.  That's the heart of the issue -- if
> result_of were modified (only for lacking compilers) to fall back to
> decltype, then the lack of result_type wouldn't require special
> handling by the user.

That's an interesting suggestion. (Thinking ...) It requires the ability
to detect the presence or absence of a nested result<> struct template.
IIRC, this is difficult, and doesn't work on all compilers. But I could
be mistaken.

Would you be willing to open a trac ticket and attach a patch?

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Range & c++0x Lambdas] Can this be done?

Jeffrey Lee Hellrung, Jr.-2
On Thu, Nov 29, 2012 at 9:46 AM, Eric Niebler <[hidden email]> wrote:
On 11/29/2012 9:29 AM, Nathan Crookston wrote:
> Eric Niebler wrote:
>> Here's the surprising part:
>>
>> Jeffrey Lee Hellrung, Jr. wrote:
>>> - 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.
>
> I understood the suggestion to apply when compilers had pre-3276
> decltype -- so the above wouldn't apply to latest clang, nor to
> other compilers once they support incomplete types.

Ah. Forgive me for having misunderstood the suggestion.

>> 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?
>
> No, they're not required.  That's the heart of the issue -- if
> result_of were modified (only for lacking compilers) to fall back to
> decltype, then the lack of result_type wouldn't require special
> handling by the user.

That's an interesting suggestion. (Thinking ...) It requires the ability
to detect the presence or absence of a nested result<> struct template.

Yes.
 
IIRC, this is difficult, and doesn't work on all compilers.

It's not so different from detecting the presence of result_type; hopefully compilers with lambdas and weak decltype are sufficiently sophisticated to handle it.
 
But I could
be mistaken.

Would you be willing to open a trac ticket and attach a patch?

I can put it on the my TODO list :)

- Jeff


_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Range & c++0x Lambdas] Can this be done?

Nate Crookston
In reply to this post by Jeffrey Lee Hellrung, Jr.-2

Jeffrey Lee Hellrung, Jr. wrote:
Sorry, this probably came earlier in the thread, but I suppose you have a ticket + patch lying around somewhere? Or has a Boost.Range maintainer agreed to implement these changes?
 
https://svn.boost.org/trac/boost/ticket/7748 (includes patch + tests)

No response from a maintainer, thus far, however.

Nate




_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Range & c++0x Lambdas] Can this be done?

Nate Crookston
In reply to this post by Jeffrey Lee Hellrung, Jr.-2
Jeffrey Lee Hellrung, Jr. wrote:
Eric Niebler wrote:
That's an interesting suggestion. (Thinking ...) It requires the ability
to detect the presence or absence of a nested result<> struct template.

Yes.
 
IIRC, this is difficult, and doesn't work on all compilers.

It's not so different from detecting the presence of result_type; hopefully compilers with lambdas and weak decltype are sufficiently sophisticated to handle it.

The fallback could always be predicated on BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE as well, though I suspect that's defined for all compilers with decltype.
 

Would you be willing to open a trac ticket and attach a patch?

I can put it on the my TODO list :)
 
If you don't have time for this soon, I could probably do this tonight -- if it's not stepping on your toes. . .

Thanks,
Nate


_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Range & c++0x Lambdas] Can this be done?

Jeffrey Lee Hellrung, Jr.-2
On Thu, Nov 29, 2012 at 10:02 AM, Nathan Crookston <[hidden email]> wrote:
Jeffrey Lee Hellrung, Jr. wrote:
Eric Niebler wrote:
That's an interesting suggestion. (Thinking ...) It requires the ability
to detect the presence or absence of a nested result<> struct template.

Yes.
 
IIRC, this is difficult, and doesn't work on all compilers.

It's not so different from detecting the presence of result_type; hopefully compilers with lambdas and weak decltype are sufficiently sophisticated to handle it.

The fallback could always be predicated on BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE as well, though I suspect that's defined for all compilers with decltype.
 

Would you be willing to open a trac ticket and attach a patch?

I can put it on the my TODO list :)
 
If you don't have time for this soon, I could probably do this tonight -- if it's not stepping on your toes. . .

Not at all, be my guest!

- Jeff


_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Range & c++0x Lambdas] Can this be done?

Eric Niebler-3
In reply to this post by Nate Crookston
On 11/29/2012 10:02 AM, Nathan Crookston wrote:
> If you don't have time for this soon, I could probably do this tonight
> -- if it's not stepping on your toes. . .

Don't forget tests and docs. :-)

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Range & c++0x Lambdas] Can this be done?

Nate Crookston
All,

Eric Niebler wrote:
Don't forget tests and docs. :-)

Thanks, I would have forgotten the docs.  I've attempted to post the patch with the ticket[1], but it's being rejected as potential spam (due to external links in the doc changes) & the captcha isn't displayed (on chrome at least).

I'll attach it here; I'd appreciate it if someone with an actual trac login could attach it for me (feel free to close 7754 as well).  Please look over the patch -- all comments are welcome, particularly on improving test code coverage.

Thanks,
Nate




_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users

result_of.diff (18K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [Range & c++0x Lambdas] Can this be done?

Michel MORIN
Nathan Crookston wrote:

> Eric Niebler wrote:
>> Don't forget tests and docs. :-)
>
>
> Thanks, I would have forgotten the docs.  I've attempted to post the patch
> with the ticket[1], but it's being rejected as potential spam (due to
> external links in the doc changes) & the captcha isn't displayed (on chrome
> at least).
>
> I'll attach it here; I'd appreciate it if someone with an actual trac login
> could attach it for me (feel free to close 7754 as well).

Attached a patch by Nathan Crookston to #7753
  https://svn.boost.org/trac/boost/ticket/7753

Closed #7754 as duplicate.

Regards,
Michel
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
12