On Sun, Apr 21, 2013 at 7:48 AM, Daniel Walker <daniel.j.walker@gmail.com>wrote:
On Apr 21, 2013, at 3:04 AM, "Vicente J. Botet Escriba" < vicente.botet@wanadoo.fr> wrote:
Hi Daniel,
Daniel Walker wrote:
Nathan Crookston wrote:
I just wanted to ping on this; see if someone's had time to review the patch. I failed to mention that the same parts of the full test suite passes on VC10 before and after the patch, so there's some assurance
it's correct. OK, I finally had a chance to look at the patch. The implementation is fine, but the configuration, documentation and tests allow/imply that BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK is enabled by default on certain compilers. I believe we should not stealthily change the default behavior. It seems to me that the migration path we adopted years ago should remain in place: the default behavior of boost:result_of will only change if your compile supports N3276, in which case you will get the full decltype implementation.
I think it would be best to introduce this functionality as a third option; i.e. one that the user opts into by explicitly defining BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK. (That's a good name for the macro, BTW.) If you could update the patch, I'd be glad to apply it.
Thanks for looking over the patch! I'd be happy to make the change, if that means getting the functionality into boost. However, I think that
Le 20/04/13 23:25, Nathan Crookston a écrit : that the
decltype fallback should be enabled at least for those compilers which have both a lacking decltype implementation and C++11 lambdas. This doesn't change the migration path, of course -- as N3276 is implemented in more compilers, more compilers will use the straight (standards conforming) decltype implementation.
I don't think there are typical situations where someone using lambda functions would *not* want boost::result_of to work for it. However, I'll submit a patch updated as you request in a few days, unless I and/or others can help change your mind. ;)
Could, defining BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK by default on these compilers, result on a regression on these compilers?
If not it should be done as it allows to take care of more cases.
Do we know of some regression cases?
It's not a matter of regressions but user expectations. boost::result_of's documentation has said for a long time now that if decltype is not used then TR1 is. It doesn't seem like a good idea to me to introduce a new default scenario, a hybrid, which is a little hard to explain.
Fair enough, but I don't think the fact that it's difficult to explain should, in and of itself, preclude its introduction.
Everything is easier if there is one switch between two standards for the default behavior, namely, support for N3276.
Well, not universally. Those who want result_of to work with C++11 lambda's on compilers which do no support N3276 will find this new default scenario easier, I imagine. However, there will also be regressions, i.e. valid user code that will no
longer compile if we change the default. An obvious one is user code that is conditioned on the current two modes. If we change the default to a new third mode, then such code will suddenly fail to compile in the default case. For example:
struct functor { template<class T> T operator()(T); };
template<class T> struct S { #ifdef BOOST_RESULT_OF_USE_DECLTYPE typedef boost::result_of<functor(T)>::type type; #endif
#ifdef BOOST_RESULT_OF_USE_TR1 struct TR1functor { template <class> struct result; template<class F, class U> struct result<F(U)> { typedef T type; };
template<class U> U operator()(U); };
typedef typename boost::result_of<TR1functor(T)>::type type; #endif };
typedef S<int>::type type; // error if the default changes
Is this excised from actual code or a purely contrived example? Is it documented that we guarantee that defined( USE_DECLTYPE ) ^ defined( USE_TR1 ) ? If so, this seems like a brittle and overspecified guarantee to begin with. Anyways, at worst, can't we just define USE_TR1 for the hybrid result_of anyway? There will be more subtle errors as well. The following will compile by
default on compilers with insufficient decltype support, since TR1 is used by default, but it will fail if we change the default to the hybrid mode.
struct functor { int operator()(); };
BOOST_STATIC_ASSERT(( boost::is_same<boost::result_of<functor()>::type, void>::value ));
This is due to a dark corner of TR1: the result and result_type members are consulted in non-nullary functors but nullary functors always generate void. (See the section on known difference between boost::result_of and TR1 in the documentation.)
The rationale for this always confused me, with the end result (it seems) that it makes TR1 result_of basically unusable for nullary function calls. In any case, again, at worst, we can retain this (dare I say, questionable?) behavior for nullary function calls for hybrid result_of. - Jeff