[result_of] Allow result_of to work with C++11 lambdas
Hi all, Using C++11 lambda functions with several boost components. For example, the following code snippet will not work with VC10, nor with g++ up to 4.8: #include <boost/assign.hpp> #include <boost/range/adaptors.hpp> #include <boost/range/algorithm.hpp> #include <iostream> int main() { std::vector<int> v; for(int i = 0; i < 10; ++i) v.push_back(i); boost::for_each(v | boost::adaptors::transformed([](int i) { return i * 2; }), [](int i) { std::cout << i << std::endl; }); } g++4.5 gives around 34k of error messages, while VC10 has a mere 22k. The root of these problems is that lambda functions don't conform to the tr1::result_of protocol -- there is no nested result_type member, nor nested result struct. The standard doesn't mandate this case since decltype may be used to deduce the return type on C++11-conforming compilers. boost::result_of disables the use of decltype on many compilers in favor of tr1-style deduction due to weaknesses in the implementation of decltype. While it is important to use tr1-protocol result_of to allow code involving incomplete types to compile, it would be very convenient to fall back to a decltype approach when it's detected that the tr1 protocol is not being followed. Jeff Hellrung suggested[1] a fallback to decltype *only* for compilers which had nonconforming decltype operators. Thus the only behavioral change would be that some code which before would produce an error would now compile and run correctly. A ticket[1] with a patch (including tests and docs) was created. Daniel Walker suggested further discussion on the list, which this attempts to provoke. I think this would be a nice improvement for a set of often-used compilers -- the list of boost-users questions whose problems could be addressed by this patch is extensive (and can be provided, if desired). Thanks, Nate [1] http://boost.2283326.n4.nabble.com/Range-amp-c-0x-Lambdas-Can-this-be-done-td4638947i20.html<http://boost.2283326.n4.nabble.com/Range-amp-c-0x-Lambdas-Can-this-be-done-td4638947i20.html> [2] https://svn.boost.org/trac/boost/ticket/7753
On 13-04-08 10:50 PM, Nathan Crookston wrote:
Hi all,
Using C++11 lambda functions with several boost components. For example, the following code snippet will not work with VC10, nor with g++ up to 4.8:
#include <boost/assign.hpp> #include <boost/range/adaptors.hpp> #include <boost/range/algorithm.hpp> #include <iostream>
int main() { std::vector<int> v; for(int i = 0; i < 10; ++i) v.push_back(i);
boost::for_each(v | boost::adaptors::transformed([](int i) { return i * 2; }), [](int i) { std::cout << i << std::endl; }); }
g++4.5 gives around 34k of error messages, while VC10 has a mere 22k.
The root of these problems is that lambda functions don't conform to the tr1::result_of protocol -- there is no nested result_type member, nor nested result struct. The standard doesn't mandate this case since decltype may be used to deduce the return type on C++11-conforming compilers.
boost::result_of disables the use of decltype on many compilers in favor of tr1-style deduction due to weaknesses in the implementation of decltype. While it is important to use tr1-protocol result_of to allow code involving incomplete types to compile, it would be very convenient to fall back to a decltype approach when it's detected that the tr1 protocol is not being followed.
Jeff Hellrung suggested[1] a fallback to decltype *only* for compilers which had nonconforming decltype operators. Thus the only behavioral change would be that some code which before would produce an error would now compile and run correctly.
A ticket[1] with a patch (including tests and docs) was created. Daniel Walker suggested further discussion on the list, which this attempts to provoke. I think this would be a nice improvement for a set of often-used compilers -- the list of boost-users questions whose problems could be addressed by this patch is extensive (and can be provided, if desired).
Thanks, Nate
[1] http://boost.2283326.n4.nabble.com/Range-amp-c-0x-Lambdas-Can-this-be-done-td4638947i20.html<http://boost.2283326.n4.nabble.com/Range-amp-c-0x-Lambdas-Can-this-be-done-td4638947i20.html> [2] https://svn.boost.org/trac/boost/ticket/7753
For the record, I'm in favor of this. Daniel Walker is the maintainer of result_of, but I've occasionally made changes myself. I haven't looked at the patch in question, but it's been on my todo list for a long time. My todo list has gotten pretty long, so if you or Daniel beat me to it, bonus. -- Eric Niebler Boost.org
On Apr 9, 2013, at 2:05 AM, Eric Niebler <eniebler@boost.org> wrote:
On 13-04-08 10:50 PM, Nathan Crookston wrote:
Hi all,
Using C++11 lambda functions with several boost components. For example, the following code snippet will not work with VC10, nor with g++ up to 4.8:
#include <boost/assign.hpp> #include <boost/range/adaptors.hpp> #include <boost/range/algorithm.hpp> #include <iostream>
int main() { std::vector<int> v; for(int i = 0; i < 10; ++i) v.push_back(i);
boost::for_each(v | boost::adaptors::transformed([](int i) { return i * 2; }), [](int i) { std::cout << i << std::endl; }); }
g++4.5 gives around 34k of error messages, while VC10 has a mere 22k.
The root of these problems is that lambda functions don't conform to the tr1::result_of protocol -- there is no nested result_type member, nor nested result struct. The standard doesn't mandate this case since decltype may be used to deduce the return type on C++11-conforming compilers.
boost::result_of disables the use of decltype on many compilers in favor of tr1-style deduction due to weaknesses in the implementation of decltype. While it is important to use tr1-protocol result_of to allow code involving incomplete types to compile, it would be very convenient to fall back to a decltype approach when it's detected that the tr1 protocol is not being followed.
Jeff Hellrung suggested[1] a fallback to decltype *only* for compilers which had nonconforming decltype operators. Thus the only behavioral change would be that some code which before would produce an error would now compile and run correctly.
A ticket[1] with a patch (including tests and docs) was created. Daniel Walker suggested further discussion on the list, which this attempts to provoke. I think this would be a nice improvement for a set of often-used compilers -- the list of boost-users questions whose problems could be addressed by this patch is extensive (and can be provided, if desired).
Thanks, Nate
[1] http://boost.2283326.n4.nabble.com/Range-amp-c-0x-Lambdas-Can-this-be-done-td4638947i20.html<http://boost.2283326.n4.nabble.com/Range-amp-c-0x-Lambdas-Can-this-be-done-td4638947i20.html> [2] https://svn.boost.org/trac/boost/ticket/7753
For the record, I'm in favor of this. Daniel Walker is the maintainer of result_of, but I've occasionally made changes myself. I haven't looked at the patch in question, but it's been on my todo list for a long time. My todo list has gotten pretty long, so if you or Daniel beat me to it, bonus.
I like the idea as well. I could devote some time to this and look at the patch again if there is any interest. - Daniel
Hi all, Daniel Walker wrote:
Eric Niebler wrote:
On 13-04-08 10:50 PM, Nathan Crookston wrote:
Jeff Hellrung suggested[1] a fallback to decltype *only* for compilers which had nonconforming decltype operators. Thus the only behavioral change would be that some code which before would produce an error would now compile and run correctly.
A ticket[1] with a patch (including tests and docs) was created. Daniel Walker suggested further discussion on the list, which this attempts to provoke. I think this would be a nice improvement for a set of often-used compilers -- the list of boost-users questions whose problems could be addressed by this patch is extensive (and can be provided, if desired).
For the record, I'm in favor of this. Daniel Walker is the maintainer of result_of, but I've occasionally made changes myself. I haven't looked at the patch in question, but it's been on my todo list for a long time. My todo list has gotten pretty long, so if you or Daniel beat me to it, bonus.
I like the idea as well. I could devote some time to this and look at the patch again if there is any interest.
I actually updated the patch to use the BOOST_NO_CXX11_* style macros, and merge cleanly with current trunk. I'll attach it to the ticket when I'm at my computer with the patch. The basics of the current patch are unchanged, however. Thanks, Nate
Le 09/04/13 07:50, Nathan Crookston a écrit :
Jeff Hellrung suggested[1] a fallback to decltype *only* for compilers which had nonconforming decltype operators. Thus the only behavioral change would be that some code which before would produce an error would now compile and run correctly.
Hi, how a Boost library as Boost.Thread could use the new boost::result_of? Should it provide different implementations depending on whether BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK are defined? Best, Vicente
Hi Vicente, Vicente J. Botet Escriba wrote:
Le 09/04/13 07:50, Nathan Crookston a écrit :
Jeff Hellrung suggested[1] a fallback to decltype *only* for compilers
which had nonconforming decltype operators. Thus the only behavioral change would be that some code which before would produce an error would now compile and run correctly.
Hi,
how a Boost library as Boost.Thread could use the new boost::result_of? Should it provide different implementations depending on whether BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK are defined?
I'm not sure I understand what you mean. Which piece of boost thread would need to provide different implementations depending on the macro defined? I don't think users usually care about which version of result_of is actually selected -- unless deduction doesn't work, which is the case for C++11 lambdas currently. Do you have an example where the user would need to write their code differently depending on the chosen result_of implementation? I can only think of times where a user may wish to explicitly select one type. Thanks, Nate
Le 10/04/13 18:16, Nathan Crookston a écrit :
Hi Vicente,
Vicente J. Botet Escriba wrote:
Le 09/04/13 07:50, Nathan Crookston a écrit :
Jeff Hellrung suggested[1] a fallback to decltype *only* for compilers
which had nonconforming decltype operators. Thus the only behavioral change would be that some code which before would produce an error would now compile and run correctly.
Hi,
how a Boost library as Boost.Thread could use the new boost::result_of? Should it provide different implementations depending on whether BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK are defined?
I'm not sure I understand what you mean. Which piece of boost thread would need to provide different implementations depending on the macro defined? I don't think users usually care about which version of result_of is actually selected -- unless deduction doesn't work, which is the case for C++11 lambdas currently. Do you have an example where the user would need to write their code differently depending on the chosen result_of implementation? I can only think of times where a user may wish to explicitly select one type.
The problem is that result_of for compatibility problems is not able to choose the version of result_of that works the better. So the user needs to define one of these macros to select the best adapted to his needs. But a Boost library needs to be portable and needs a result_of that works the best depending on the compiler and the context used. Maybe we need another result_of that has no backward compatibility issues. Please let me know if I'm not enough clear or even wrong. Best, Vicente
Hi Vicente, Vicente J. Botet Escriba wrote:
The problem is that result_of for compatibility problems is not able to choose the version of result_of that works the better. So the user needs to define one of these macros to select the best adapted to his needs. But a Boost library needs to be portable and needs a result_of that works the best depending on the compiler and the context used. Maybe we need another result_of that has no backward compatibility issues.
If I'm understanding correctly, you're suggesting that compatibility problems are the reason result_of doesn't use the decltype-based implementation. If so, I don't think it's quite true. The reason why decltype isn't used for more compilers is that deduction fails in some cases where incomplete types are involved[1]. This isn't so much a backwards-compatibility issue since we'd like result_of to work in such cases, even today. I think individual boost libraries shouldn't need to worry about the macros. Users may need to explicitly define one of the macros if they develop on a compiler which supports decltype-based result_of, but wish to support compilers without decltype. In short, I think that (with the decltype fallback) result_of *will* choose the best implementation, and (if the patch is applied) defining a macro to explicitly select a back end should be done for cross-platform compatibility reasons. Thanks, Nate [1] http://lists.boost.org/Archives/boost/2010/04/164714.php -- very instructive discussion
On 10/04/13 19:12, Nathan Crookston wrote:
Hi Vicente,
Vicente J. Botet Escriba wrote:
The problem is that result_of for compatibility problems is not able to choose the version of result_of that works the better. So the user needs to define one of these macros to select the best adapted to his needs. But a Boost library needs to be portable and needs a result_of that works the best depending on the compiler and the context used. Maybe we need another result_of that has no backward compatibility issues.
If I'm understanding correctly, you're suggesting that compatibility problems are the reason result_of doesn't use the decltype-based implementation. If so, I don't think it's quite true. The reason why decltype isn't used for more compilers is that deduction fails in some cases where incomplete types are involved[1]. This isn't so much a backwards-compatibility issue since we'd like result_of to work in such cases, even today.
There are indeed compatibility problems to using decltype *instead of the result_of protocol*. This is not what's proposed here though, it's proposed that decltype be used *if the type does not follow the result_of protocol*. The proposed change is fully backwards-compatible. I personally have my own implementation of result_of which does this. My implementation is also simpler, compiles faster, is optionally optimized for compilers with variadic templates (also supports compilers with decltype but no variadic templates), has preprocessing support, and has the added benefit that result_of<Sig>::type is only defined if Sig is callable.
Hi Mathias, Mathias Gaunard wrote:
I personally have my own implementation of result_of which does this. My implementation is also simpler, compiles faster, is optionally optimized for compilers with variadic templates (also supports compilers with decltype but no variadic templates), has preprocessing support, and has the added benefit that result_of<Sig>::type is only defined if Sig is callable.
Sounds pretty slick. Is this in NT2, or just in some other code you have? Just so it's clear to others on the list, boost::result_of (at least in trunk) also has result_of<Sig>::type that is only defined when Sig is callable. I believe Eric Niebler added that a while back. Thanks, Nate
On 10/04/13 19:43, Nathan Crookston wrote:
Hi Mathias,
Mathias Gaunard wrote:
I personally have my own implementation of result_of which does this. My implementation is also simpler, compiles faster, is optionally optimized for compilers with variadic templates (also supports compilers with decltype but no variadic templates), has preprocessing support, and has the added benefit that result_of<Sig>::type is only defined if Sig is callable.
Sounds pretty slick. Is this in NT2, or just in some other code you have?
Yes. I've found that boost::result_of is often a performance bottleneck. Unfortunately the code in Boost is not as simple as it could be; it instantiates way too many templates, I suppose for legacy purposes. My version could probably still be improved too.
Just so it's clear to others on the list, boost::result_of (at least in trunk) also has result_of<Sig>::type that is only defined when Sig is callable. I believe Eric Niebler added that a while back.
Doesn't work with latest trunk. The code below doesn't compile. /home/mgaunard/dev/boost/trunk/boost/utility/result_of.hpp:173:8: error: no class template named ‘result’ in ‘struct foo’ It does work, however, if instructed to use decltype. My version applies SFINAE in C++03 and without SFINAE for expressions too. #include <boost/utility/result_of.hpp> #include <iostream> struct foo {}; template<class T> typename boost::result_of<T(int)>::type bar(T const& t); void bar(...) { std::cout << "not callable" << std::endl; } int main() { bar(foo()); }
On 10/04/13 19:43, Nathan Crookston wrote:
Hi Mathias,
Mathias Gaunard wrote:
I personally have my own implementation of result_of which does this. My
implementation is also simpler, compiles faster, is optionally optimized for compilers with variadic templates (also supports compilers with decltype but no variadic templates), has preprocessing support, and has the added benefit that result_of<Sig>::type is only defined if Sig is callable.
Sounds pretty slick. Is this in NT2, or just in some other code you have?
Yes. I've found that boost::result_of is often a performance bottleneck. Unfortunately the code in Boost is not as simple as it could be; it instantiates way too many templates, I suppose for legacy purposes. My version could probably still be improved too.
I actually gave this a try with some code that used to cause the decltype-based boost::result_of problems. It worked well, not matter which
Hi Mathias, Mathias Gaunard wrote: preprocessor symbols I defined. The code and the later fix were both provided by Eric Niebler, btw (I made minor modifications). #define USE_RESULT_OF //#define BOOST_RESULT_OF_USE_DECLTYPE #define BOOST_RESULT_OF_USE_TR1 #ifndef USE_NT2_RESULT_OF # include <boost/utility/result_of.hpp> namespace ro = boost; #else # include <boost/dispatch/meta/result_of.hpp> namespace ro = boost::dispatch::meta; #endif #include <utility> template <typename T> T const& cref(); template <typename T> T& ref(); template <typename F, typename Arg> typename ro::result_of<F(Arg const&)>::type invoke(F f, Arg const& arg) { return f(arg); } template <typename F, typename Arg> typename ro::result_of<F(Arg&)>::type invoke(F f, Arg& arg) { return f(arg); } /////////////////////////////////////////////////////////////////////////////// // Client code /////////////////////////////////////////////////////////////////////////////// #include <iostream> int foo(int& i) { std::cout << i << std::endl; return i; } int main() { int i = 123; invoke(foo, i); } In short, your implementation seems to work well for every tricky case I tried. Do you perchance have metrics on the difference in # of instantiations, or compile time? I'm just curious. Thanks, Nate
Le 10/04/13 19:12, Nathan Crookston a écrit :
Hi Vicente,
Vicente J. Botet Escriba wrote:
The problem is that result_of for compatibility problems is not able to choose the version of result_of that works the better. So the user needs to define one of these macros to select the best adapted to his needs. But a Boost library needs to be portable and needs a result_of that works the best depending on the compiler and the context used. Maybe we need another result_of that has no backward compatibility issues.
If I'm understanding correctly, you're suggesting that compatibility problems are the reason result_of doesn't use the decltype-based implementation. If so, I don't think it's quite true. The reason why decltype isn't used for more compilers is that deduction fails in some cases where incomplete types are involved[1]. This isn't so much a backwards-compatibility issue since we'd like result_of to work in such cases, even today.
I think individual boost libraries shouldn't need to worry about the macros. Users may need to explicitly define one of the macros if they develop on a compiler which supports decltype-based result_of, but wish to support compilers without decltype.
In short, I think that (with the decltype fallback) result_of *will* choose the best implementation, and (if the patch is applied) defining a macro to explicitly select a back end should be done for cross-platform compatibility reasons.
Thanks, Nate
[1] http://lists.boost.org/Archives/boost/2010/04/164714.php -- very instructive discussion
If you are right and after the patch result_of would provide the best we can do now, why the user would need to define any of these macros? Vicente
On 10/04/13 19:27, Vicente J. Botet Escriba wrote:
If you are right and after the patch result_of would provide the best we can do now, why the user would need to define any of these macros?
Using decltype directly could offer a compile-time performance boost. That's about it as far as I can tell.
Hi Vicente, Vicente J. Botet Escriba wrote:
Le 10/04/13 19:12, Nathan Crookston a écrit :
I think individual boost libraries shouldn't need to worry about the
macros. Users may need to explicitly define one of the macros if they develop on a compiler which supports decltype-based result_of, but wish to support compilers without decltype.
In short, I think that (with the decltype fallback) result_of *will* choose the best implementation, and (if the patch is applied) defining a macro to explicitly select a back end should be done for cross-platform compatibility reasons.
If you are right and after the patch result_of would provide the best we can do now, why the user would need to define any of these macros?
I think it would be uncommon for the user to define those macros. Here's a situation where it may be useful: I have a library which I claim supports VC9 and Clang. I do my development with clang 3.2, and rely on some form of automated testing to verify it works with MSVC. I may commonly forget to add result_type or a nested struct to my functors, since clang uses decltype. After the Nth time, I may, during my own development, #define BOOST_RESULT_OF_USE_TR1, just so that I'm not continually breaking the VC9 build. So again, I think it's uncommon. Thanks, Nate
Hi Vicente,
Vicente J. Botet Escriba wrote:
Le 10/04/13 19:12, Nathan Crookston a écrit :
I think individual boost libraries shouldn't need to worry about the
macros. Users may need to explicitly define one of the macros if they develop on a compiler which supports decltype-based result_of, but wish to support compilers without decltype.
In short, I think that (with the decltype fallback) result_of *will* choose the best implementation, and (if the patch is applied) defining a macro to explicitly select a back end should be done for cross-platform compatibility reasons.
If you are right and after the patch result_of would provide the best we can do now, why the user would need to define any of these macros?
I think it would be uncommon for the user to define those macros. Here's a situation where it may be useful:
I have a library which I claim supports VC9 and Clang. I do my development with clang 3.2, and rely on some form of automated testing to verify it works with MSVC. I may commonly forget to add result_type or a nested struct to my functors, since clang uses decltype. After the Nth time, I may, during my own development, #define BOOST_RESULT_OF_USE_TR1, just so that I'm not continually breaking the VC9 build.
So again, I think it's uncommon. Do you mean that if a library author develops and tests with both compilers an even more at once he would need to define BOOST_RESULT_OF_USE_TR1 from the beginning even if defining BOOST_RESULT_OF_USE_DECTYPE works better on some compilers? But the
Le 10/04/13 19:39, Nathan Crookston a écrit : library author cannot know how the users would define their Functors so it can not define these macros. I think that I need to re-read the result_of documentation to understand correctly what is proposed. Thanks for your clarifications, Vicente
Hi Vicente, Vicente J. Botet Escriba wrote:
Le 10/04/13 19:39, Nathan Crookston a écrit : I think it would be uncommon for the user to define those macros. Here's a
situation where it may be useful:
I have a library which I claim supports VC9 and Clang. I do my development with clang 3.2, and rely on some form of automated testing to verify it works with MSVC. I may commonly forget to add result_type or a nested struct to my functors, since clang uses decltype. After the Nth time, I may, during my own development, #define BOOST_RESULT_OF_USE_TR1, just so that I'm not continually breaking the VC9 build.
So again, I think it's uncommon.
Do you mean that if a library author develops and tests with both compilers an even more at once he would need to define BOOST_RESULT_OF_USE_TR1 from the beginning even if defining BOOST_RESULT_OF_USE_DECTYPE works better on some compilers? But the library author cannot know how the users would define their Functors so it can not define these macros.
No, I don't mean that. I mean the library author may choose to do that during development, just to avoid writing code that can't be used with a less capable compiler. In my mind, it's like enabling certain warnings on MSVC so that my code is more likely portable to g++ later. I think most people should (and will) leave the macros alone, so the best variant is detected for their platform. Nate
On 10/04/13 20:09, Vicente J. Botet Escriba wrote:
Do you mean that if a library author develops and tests with both compilers an even more at once he would need to define BOOST_RESULT_OF_USE_TR1 from the beginning even if defining BOOST_RESULT_OF_USE_DECTYPE works better on some compilers? But the library author cannot know how the users would define their Functors so it can not define these macros.
I think that I need to re-read the result_of documentation to understand correctly what is proposed.
All configurations need to be tested. Testing just RESULT_OF_USE_TR1 is not enough.
On Apr 10, 2013, at 2:09 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 10/04/13 19:39, Nathan Crookston a écrit :
Hi Vicente,
Vicente J. Botet Escriba wrote:
Le 10/04/13 19:12, Nathan Crookston a écrit :
I think individual boost libraries shouldn't need to worry about the
macros. Users may need to explicitly define one of the macros if they develop on a compiler which supports decltype-based result_of, but wish to support compilers without decltype.
In short, I think that (with the decltype fallback) result_of *will* choose the best implementation, and (if the patch is applied) defining a macro to explicitly select a back end should be done for cross-platform compatibility reasons.
If you are right and after the patch result_of would provide the best we can do now, why the user would need to define any of these macros?
I think it would be uncommon for the user to define those macros. Here's a situation where it may be useful:
I have a library which I claim supports VC9 and Clang. I do my development with clang 3.2, and rely on some form of automated testing to verify it works with MSVC. I may commonly forget to add result_type or a nested struct to my functors, since clang uses decltype. After the Nth time, I may, during my own development, #define BOOST_RESULT_OF_USE_TR1, just so that I'm not continually breaking the VC9 build.
So again, I think it's uncommon. Do you mean that if a library author develops and tests with both compilers an even more at once he would need to define BOOST_RESULT_OF_USE_TR1 from the beginning even if defining BOOST_RESULT_OF_USE_DECTYPE works better on some compilers? But the library author cannot know how the users would define their Functors so it can not define these macros.
I think that I need to re-read the result_of documentation to understand correctly what is proposed.
I had thought of this proposal as a third configuration. So, our established migration path from using TR1 by default to using decltype by default would remain, but we would add a third option: a hybrid that could switch between TR1 mode and decltype mode smartly. - Daniel
Vicente J. Botet Escriba wrote:
Do you mean that if a library author develops and tests with both compilers an even more at once he would need to define BOOST_RESULT_OF_USE_TR1 from the beginning even if defining BOOST_RESULT_OF_USE_DECTYPE works better on some compilers? But the library author cannot know how the users would define their Functors so it can not define these macros.
I think that I need to re-read the result_of documentation to understand correctly what is proposed.
I had thought of this proposal as a third configuration. So, our established migration path from using TR1 by default to using decltype by default would remain, but we would add a third option: a hybrid that could switch between TR1 mode and decltype mode smartly.
Agreed. Hopefully I didn't take the discussion too far afield. The
Daniel Walker wrote: proposal is what you describe, and I believe the main impetus to accept it is so C++11 lambdas can be used in result_of expressions on compilers which have lacking lambdas. Thanks, Nate
Nathan Crookston wrote:
Agreed. Hopefully I didn't take the discussion too far afield. The proposal is what you describe, and I believe the main impetus to accept it is so C++11 lambdas can be used in result_of expressions on compilers which have lacking lambdas.
Ugh. I meant "lacking decltype implementations." Nate
Hi all, Nathan Crookston wrote:
Nathan Crookston wrote:
Agreed. Hopefully I didn't take the discussion too far afield. The proposal is what you describe, and I believe the main impetus to accept it is so C++11 lambdas can be used in result_of expressions on compilers which have lacking lambdas.
Ugh. I meant "lacking decltype implementations."
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 that it's correct. Thanks, Nate
On Apr 18, 2013, at 11:53 PM, Nathan Crookston <nathan.crookston@gmail.com> wrote:
Hi all,
Nathan Crookston wrote:
Nathan Crookston wrote:
Agreed. Hopefully I didn't take the discussion too far afield. The proposal is what you describe, and I believe the main impetus to accept it is so C++11 lambdas can be used in result_of expressions on compilers which have lacking lambdas.
Ugh. I meant "lacking decltype implementations."
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 that 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. - Daniel
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 that 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 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. ;) Thanks, Nate
Le 20/04/13 23:25, Nathan Crookston a écrit :
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 that 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 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? Vicente
On Apr 21, 2013, at 3:04 AM, "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr> wrote:
Le 20/04/13 23:25, Nathan Crookston a écrit :
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 that 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 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. Everything is easier if there is one switch between two standards for the default behavior, namely, support for N3276. 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 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.) - Daniel
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
Jeffrey Lee Hellrung, Jr. wrote:
On Sun, Apr 21, 2013 at 7:48 AM, Daniel Walker <daniel.j.walker@gmail.com>wrote:
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.
result_type is consulted. result<> is not. type is void (instead of a compile error) when there is no result_type. The reason for the type being void is that in template<class T> class reference_wrapper { private: T & t_; public: typename result_of<T()>::type operator()() const { return t_(); } }; operator()() is not a template. If result_of<T()>::type wasn't present or generated an error when T doesn't have result<>, reference_wrapper<int> would have generated an error when instantiated. In C++11, you can make operator()() a template. In C++03, you can't.
On Sun, Apr 21, 2013 at 6:35 PM, Peter Dimov <lists@pdimov.com> wrote:
Jeffrey Lee Hellrung, Jr. wrote:
On Sun, Apr 21, 2013 at 7:48 AM, Daniel Walker <daniel.j.walker@gmail.com
**wrote: 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.
result_type is consulted. result<> is not. type is void (instead of a compile error) when there is no result_type.
The reason for the type being void is that in
template<class T> class reference_wrapper { private:
T & t_;
public:
typename result_of<T()>::type operator()() const { return t_(); } };
operator()() is not a template. If result_of<T()>::type wasn't present or generated an error when T doesn't have result<>, reference_wrapper<int> would have generated an error when instantiated.
In C++11, you can make operator()() a template. In C++03, you can't.
Oh. Right. I believe this can be worked around by conditionally defining operator()() (by conditionally inheriting from various base classes) only if T has operator()(), but that's a more complex solution. - Jeff
On Apr 21, 2013, at 9:35 PM, "Peter Dimov" <lists@pdimov.com> wrote:
Jeffrey Lee Hellrung, Jr. wrote:
On Sun, Apr 21, 2013 at 7:48 AM, Daniel Walker <daniel.j.walker@gmail.com>wrote:
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.
result_type is consulted. result<> is not. type is void (instead of a compile error) when there is no result_type.
The reason for the type being void is that in
template<class T> class reference_wrapper { private:
T & t_;
public:
typename result_of<T()>::type operator()() const { return t_(); } };
operator()() is not a template. If result_of<T()>::type wasn't present or generated an error when T doesn't have result<>, reference_wrapper<int> would have generated an error when instantiated.
In C++11, you can make operator()() a template. In C++03, you can't.
Thanks Peter. I forgot that you can still use result_type with nullary functors. I feel like I haven't used TR1 in a while... - Daniel
Daniel Walker wrote:
I feel like I haven't used TR1 in a while...
I can't think of a reason to ever use TR1 (and whichever version of result_of) in C++11. Even less so in C++14, which will have deduced return types unless the N3638 formal motion failed, and I very much hope it did not.
On Apr 21, 2013, at 10:36 PM, Peter Dimov <lists@pdimov.com> wrote:
Daniel Walker wrote:
I feel like I haven't used TR1 in a while...
I can't think of a reason to ever use TR1 (and whichever version of result_of) in C++11. Even less so in C++14, which will have deduced return types unless the N3638 formal motion failed, and I very much hope it did not.
Agreed, and we recommend in the boost::result_of documentation that C++11 users use std::result_of rather than boost::result_of. However, one reason to use TR1 in C++11 is to make code more portable to/from C++03, which is an important use-case for boost::result_of right now. This is one reason why we require explicit user action to change the default (TR1) behavior on sub-standard C++11 compilers: to promote portability and to minimize the effort needed to compile existing C++03 code. - Daniel
Daniel Walker wrote:
On Apr 21, 2013, at 10:36 PM, Peter Dimov <lists@pdimov.com> wrote:
I can't think of a reason to ever use TR1 (and whichever version of result_of) in C++11. Even less so in C++14, which will have deduced return types unless the N3638 formal motion failed, and I very much hope it did not.
Agreed, and we recommend in the boost::result_of documentation that C++11 users use std::result_of rather than boost::result_of.
I actually meant that C++11 users should use decltype directly rather than result_of. A library that wanted to support both would do something like template<...> #if C++11 auto f(...) -> decltype(...) #else boost::result_of<...>::type f(...) #endif { ... } That's not very nice as it forces you to write everything twice, but it keeps C++11 users isolated from anything C++03-related. In particular, it no longer matters whether boost::result_of works with lambdas. (Well... it could matter if decltype is not N32whatever but lambdas work fine, but ideally, it shouldn't.)
On Apr 27, 2013, at 12:40 PM, "Peter Dimov" <lists@pdimov.com> wrote:
Daniel Walker wrote:
On Apr 21, 2013, at 10:36 PM, Peter Dimov <lists@pdimov.com> wrote:
I can't think of a reason to ever use TR1 (and whichever version of > result_of) in C++11. Even less so in C++14, which will have deduced > return types unless the N3638 formal motion failed, and I very much hope > it did not.
Agreed, and we recommend in the boost::result_of documentation that C++11 users use std::result_of rather than boost::result_of.
I actually meant that C++11 users should use decltype directly rather than result_of.
A library that wanted to support both would do something like
template<...>
#if C++11
auto f(...) -> decltype(...)
#else
boost::result_of<...>::type f(...)
#endif
{ ... }
That's not very nice as it forces you to write everything twice, but it keeps C++11 users isolated from anything C++03-related. In particular, it no longer matters whether boost::result_of works with lambdas. (Well... it could matter if decltype is not N32whatever but lambdas work fine, but ideally, it shouldn't.)
Yeah, this could work for some folks in some situations. But there are also all those containers out there that have been generated to store results from some function. I know I've seen code like the following over the years. template<class ForwardIterator, class AuxilaryFunction> class component { typedef std::vector< typename boost::result_of< AuxilaryFunction( typename std::iterator_traits< ForwardIterator >::value_type ) >::type > auxilary_results_vector; auxilary_results_vector aux_results; AuxilaryFunction aux_function; public: void initialize(AuxilaryFunction f) { aux_function = f; } template<class OutputIterator> void process(ForwardIterator first, ForwardIterator last, OutputIterator out) { for(ForwardIterator i = first; i != last; ++i) { aux_results.push_back(aux_function(*i)); // etc. } // etc. } }; Someone with code like this could abandon C++03 entirely, if they wanted to, with s/boost::result_of/std::result_of/. Or they could replace result_of with an equivalent decltype expression, though this could get cumbersome and verbose. Or they could continue using boost::result_of for more options regarding compiler portability without having to change a line of code. - Daniel
On Apr 21, 2013, at 8:50 PM, "Jeffrey Lee Hellrung, Jr." <jeffrey.hellrung@gmail.com> wrote:
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:
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.
If we release the hybrid mode not as the default but as a third option, and we hear user feedback such as "Hybrid mode is great. I'm surprised it isn't the default," then I might advocate making it the default. Of course, we'd need to roll it out over several releases due to the potential for regressions. The first would announce the pending breaking change and then a release or to later we could release the change. In the meantime, though, I think it is best to release it as a third option that people can get their hands on right away, and then we can see how user expectations change.
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?
I would characterize this as a plausible example, but either way it demonstrates currently valid code that will break if we change the default.
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.
The nullary function case is a big hole in TR1 and a strong motivation for the use of decltype, IMHO. But you cannot retain this behavior in the hybrid; since TR1 does not require result/result_type members in nullary functors (in order to compile), so they look the same as c++11 functors. So, again this is currently valid code that will break if you change the default. There are potentially other little issues like this, which is one of the reasons we've been so slow and cautious in migrating to decltype as the default. - Daniel
On 20/04/13 22:21, Daniel Walker wrote:
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.
I think it should always be enabled when using TR1 result_of, whether decltype supports N3276 or not. Doing just that will allow a lot of code to "just work" for many people. Adding a third option is not very useful and is maintenance nightmare. It's an extension, it doesn't break any code.
On 10/04/13 13:40, Vicente J. Botet Escriba wrote:
Le 09/04/13 07:50, Nathan Crookston a écrit :
Jeff Hellrung suggested[1] a fallback to decltype *only* for compilers which had nonconforming decltype operators. Thus the only behavioral change would be that some code which before would produce an error would now compile and run correctly.
Hi,
how a Boost library as Boost.Thread could use the new boost::result_of? Should it provide different implementations depending on whether BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK are defined?
I don't see any reason to not always fallback to decltype as long as decltype is available, even if incomplete/abstract types are not well supported. It would be in a case where the code would fail to compile without the fallback anyway.
participants (7)
-
Daniel Walker
-
Eric Niebler
-
Jeffrey Lee Hellrung, Jr.
-
Mathias Gaunard
-
Nathan Crookston
-
Peter Dimov
-
Vicente J. Botet Escriba