[result_of] Documentation update for ticket 7753
Hi Daniel & all, I'm updating the patch for ticket 7753 ( https://svn.boost.org/trac/boost/ticket/7753). I've made the requested changes to the patch, but I had a question on how to best explain which macro to define if, for example, you want result_of to work with C++11 lambdas. In the past, users with a pre-N3276 decltype have been advised to just #define BOOST_RESULT_OF_USE_DECLTYPE, with the explanation that "it's probably just going to work." While that advice is true, there are cases where this doesn't work; hence the addition of BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK. To explain why you'd define the FALLBACK macro over the USE_DECLTYPE macro, I'm thinking of including a paragraph like the following. "The question naturally arises on why have both BOOST_RESULT_OF_USE_DECLTYPE and BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK. In many situations, BOOST_RESULT_OF_USE_DECLTYPE will work well, even with pre-N3276 decltype. However, there are cases where a post-N3276 decltype is required to correctly deduce the return type of a functor. If a translation unit includes a functor whose return type is only deducible with TR1 or a post-N3276 decltype, using result_of with, e.g. a C++11 lambda function, will fail without BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK. If the macro BOOST_NO_CXX11_DECLTYPE_N3276 is defined and BOOST_NO_CXX11_DECLTYPE is not defined when including result_of.hpp, defining BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK is the safest option that will allow you to deduce C++11 lambda return types." My question is, am I over explaining it? Of course, I'd rather have BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK defined automatically for compilers like VC10, g++4.5, etc., and include text like the following: "If you rely on the result of calling a nullary functor to be void, regardless of the actual return type, or if your code is not written to handle cases other than BOOST_RESULT_OF_USE_TR1 and BOOST_RESULT_OF_USE_DECLTYPE, you may wish to explicitly define one of those symbols prior to including result_of." Either way, comments welcome. Thanks, Nate
On 6/19/2013 10:59 PM, Nathan Crookston wrote:
Of course, I'd rather have BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK defined automatically for compilers like VC10, g++4.5, etc.
So, why not? I haven't been following the discussion recently, but I seem to recall that we agreed to this at some point. -- Eric Niebler Boost.org http://www.boost.org
On 6/19/2013 10:59 PM, Nathan Crookston wrote:
Of course, I'd rather have BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK defined automatically for compilers like VC10, g++4.5, etc.
So, why not? I haven't been following the discussion recently, but I seem to recall that we agreed to this at some point.
Daniel looked over the patch and suggested it would be best not to define
Hi Eric, Eric Niebler wrote: the fallback mode by default. Here's the thread: http://lists.boost.org/Archives/boost/2013/04/202629.php I said I'd make a patch which follows his suggestion, but that I'd try to convince him to accept the first patch. I'll reiterate, I think it would be more surprising to have boost::result_of not work with compiler-supported lambdas than to have it correctly deduce results that would have been erroneous using TR1. Even though VC10's std::result_of didn't work with them either (for example). Thanks, Nate
On Jun 21, 2013, at 4:23 PM, Nathan Crookston
Hi Eric,
Eric Niebler wrote:
On 6/19/2013 10:59 PM, Nathan Crookston wrote:
Of course, I'd rather have BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK defined automatically for compilers like VC10, g++4.5, etc.
So, why not? I haven't been following the discussion recently, but I seem to recall that we agreed to this at some point.
Daniel looked over the patch and suggested it would be best not to define the fallback mode by default. Here's the thread:
http://lists.boost.org/Archives/boost/2013/04/202629.php
I said I'd make a patch which follows his suggestion, but that I'd try to convince him to accept the first patch. I'll reiterate, I think it would be more surprising to have boost::result_of not work with compiler-supported lambdas than to have it correctly deduce results that would have been erroneous using TR1. Even though VC10's std::result_of didn't work with them either (for example).
I am disinclined to make an unannounced change in the default behavior. If we made any change in the default, since we have already announced that we are rolling out a purely decltype-based implementation, I would prefer to loosen the N3276 requirement and simple use decltype when BOOST_HAS_DECLTYPE is defined. This would probably be less confusing to new users who seem to expect boost::result_of to act like std::result_of out of the box. However, I still like the idea of having a separate hybrid mode that would work with legacy protocols when available. (It occurred to me that this same idea has come up in the past with respect to Boost.Lambda's sig<> protocol, and it would be really cool to support both TR1 and sig<> in the hybrid mode.) - Daniel
On Jun 20, 2013, at 1:59 AM, Nathan Crookston
Hi Daniel & all,
I'm updating the patch for ticket 7753 ( https://svn.boost.org/trac/boost/ticket/7753). I've made the requested changes to the patch, but I had a question on how to best explain which macro to define if, for example, you want result_of to work with C++11 lambdas. In the past, users with a pre-N3276 decltype have been advised to just #define BOOST_RESULT_OF_USE_DECLTYPE, with the explanation that "it's probably just going to work." While that advice is true, there are cases where this doesn't work; hence the addition of BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK.
To explain why you'd define the FALLBACK macro over the USE_DECLTYPE macro, I'm thinking of including a paragraph like the following.
"The question naturally arises on why have both BOOST_RESULT_OF_USE_DECLTYPE and BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK. In many situations, BOOST_RESULT_OF_USE_DECLTYPE will work well, even with pre-N3276 decltype. However, there are cases where a post-N3276 decltype is required to correctly deduce the return type of a functor. If a translation unit includes a functor whose return type is only deducible with TR1 or a post-N3276 decltype, using result_of with, e.g. a C++11 lambda function, will fail without BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK. If the macro BOOST_NO_CXX11_DECLTYPE_N3276 is defined and BOOST_NO_CXX11_DECLTYPE is not defined when including result_of.hpp, defining BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK is the safest option that will allow you to deduce C++11 lambda return types."
My question is, am I over explaining it? Of course, I'd rather have BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK defined automatically for compilers like VC10, g++4.5, etc., and include text like the following:
"If you rely on the result of calling a nullary functor to be void, regardless of the actual return type, or if your code is not written to handle cases other than BOOST_RESULT_OF_USE_TR1 and BOOST_RESULT_OF_USE_DECLTYPE, you may wish to explicitly define one of those symbols prior to including result_of."
Either way, comments welcome.
OK, Nathan, I cleaned up your patch and committed the changes. (One more modification: I moved boost::cpp0x_result_of to boost::detail::cpp0x_result_of, since this is an implementation detail; people who are only interested in C++0x result_of should simply use std::result_of.) I added the following documentation. "Additionally, boost::result_of provides a third mode of operation, which some users may find convenient. When BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK is defined, boost::result_of behaves as follows. If the function object has a member type result_type or member template result<>, then boost::result_of will use the TR1 protocol. Otherwise, boost::result_of will use decltype. Using TR1 with a declytpe fallback may workaround certain problems at the cost of portability. For example: Deficient compiler: If your code requires boost::result_of to work with incomplete return types but your compiler's decltype implementation does not support incomplete return types, then you can use the TR1 protocol as a workaround. Support for incomplete return types was added late in the C++11 standardization process (see N3276) and is not implemented by some compilers. Deficient legacy code: If your existing TR1 function object advertises a different type than the actual result type deduced by decltype, then using TR1 with a decltype fallback will allow you to work with both your existing TR1 function objects and new C++11 function object. This situation could occur if your legacy function objects misused the TR1 protocol. See the documentation on known differences between boost::result_of and TR1." - Daniel
participants (3)
-
Daniel Walker
-
Eric Niebler
-
Nathan Crookston