|
Boost : |
Subject: Re: [boost] [result_of] now uses decltype on release branch
From: eric_at_[hidden]
Date: 2012-09-03 15:08:28
(Apologies for the top-post. I'm on the road.)
This looks good, thanks Daniel. Suggestions; don't say the TR1 protocol is "no longer required." It *is* required if you want your function objects to be portable to older compilers. I also don't know what you mean by "necessitates new behaviors". By or from whom? By and large, if people have been doing it right all along, they should be ok.
We might also point out that the idiom of specializing boost::result_of to get the right answer for nullary function objects is no longer required, and should be conditioned on BOOST_RESULT_OF_USE_DECLTYPE.
Thanks for doing this,
Eric
Sent via tiny mobile device
-----Original Message-----
From: Daniel Walker <daniel.j.walker_at_[hidden]>
Date: Mon, 3 Sep 2012 14:16:17
To: Joel de Guzman<joel_at_[hidden]>
Cc: Eric Niebler<eric_at_[hidden]>; <boost_at_[hidden]>; Michel Morin<mimomorin_at_[hidden]>; Thomas Heller<thom.heller_at_[hidden]>
Subject: Re: [result_of] now uses decltype on release branch
On Sep 1, 2012, at 8:12 PM, Joel de Guzman wrote:
> On 9/2/12 7:24 AM, Eric Niebler wrote:
>>
>> We will have to make a very BOLD announcement in the release notes of
>> 1.52. Not only will users of Phoenix be affected; anybody who relies on
>> boost::result_of to use the TR1 protocol will be broken by this. This
>> might be a painful transition for some, but there's no helping that.
>
> I have no problem with this as long as there's clear documentation
> on what users would expect and how to deal with them in their code.
Below is a first stab at documenting breaking changes for the release notes and/or result_of documentation. Is there anything I'm missing? Any caveats regarding N3276? Is this too much? Too little?
BREAKING CHANGES TO BOOST RESULT_OF
On compilers that adequately implement C++11 decltype (clang 3.1, gcc 4.7, Visual C++ 11), result_of now uses decltype by default to deduce return types rather than following the TR1 result_of protocol, which is no longer required. While this makes result_of much more useful, it also necessitates new behaviors which will break some existing code.
The following are use-cases where result_of behaves differently depending on whether decltype is used. The macro BOOST_RESULT_OF_USE_DECLTYPE is defined when result_of is using decltype. Please see the result_of documentation for more information.
1) TR1 protocol misusage
When using the TR1 protocol, result_of cannot tell whether the actual type of a call to a function object is the same as the type specified by the protocol, which allows for the possibility of inadvertent mismatches between the specified type and the actual type. When using decltype, these subtle bugs will be detected and may result in compilation errors.
struct functor {
typedef short result_type;
int operator()(short);
};
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
is_same<result_of<functor(short)>::type, int>::value
));
#else
BOOST_STATIC_ASSERT((
is_same<result_of<functor(short)>::type, short>::value
));
#endif
2) Nullary function objects
When using the TR1 protocol, result_of cannot always deduce the type of calls to nullary function objects, in which case the type defaults to void. When using decltype, result_of always gives the actual type of the call expression.
Example:
struct functor {
template<class> struct result {
typedef int type;
};
int operator()();
};
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
is_same<result_of<functor()>::type, int>::value
));
#else
BOOST_STATIC_ASSERT((
is_same<result_of<functor()>::type, void>::value
));
#endif
3) Non-class prvalues and cv-qualification
When using the TR1 protocol, result_of will report the cv-qualified type specified by the result_type or result<> members, regardless of the actual cv-qualification of the call expression. When using decltype, result_of will report the actual type of the call expression, which is not cv-qualified when the expression is a non-class prvalue.
Example:
struct functor {
template<class> struct result;
template<class F, class T> struct result<F(const T)> {
typedef const T type;
};
const short operator()(const short);
int const & operator()(int const &);
};
// Non-prvalue call expressions work the same with or without decltype.
BOOST_STATIC_ASSERT((
is_same<
result_of<functor(int const &)>::type,
int const &
>::value
));
// Non-class prvalue call expressions are not actually cv-qualified,
// but only the decltype-based result_of reports this accurately.
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
is_same<
result_of<functor(const short)>::type,
short
>::value
));
#else
BOOST_STATIC_ASSERT((
is_same<
result_of<functor(const short)>::type,
const short
>::value
));
#endif
- Daniel
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk