[utility] [swap] How about Boost.Move?
Hi, Sources of Boost.Variant have a swap implementation that takes advantage of move emulation. That code can be useful for Boost.Swap. The idea is not to use std::swap in case of ADL failure, but use a swap implementation that is aware of move emulation: namespace boost_swap_impl { namespace swap_move_emulated { template <typename T> inline void swap(T& lhs, T& rhs) { T tmp( boost::move(lhs) ); lhs = boost::move(rhs); rhs = boost::move(tmp); } } template<class T> void swap_impl(T& left, T& right) { //using namespace std;//use std::swap if argument dependent lookup fails using namespace boost_swap_impl::swap_move_emulated; swap(left,right); } // ... With that code types that use move emulation can be swapped faster and even move only types can be swapped. So, what do the community think about such optimization? -- Best regards, Antony Polukhin
25.07.2013 17:44, Antony Polukhin:
So, what do the community think about such optimization?
I thought that was already done :) (however, never relied on it) I think if it is transparent change - then it should be done. If not - then maybe introduce new "move-emulation-aware" swap? P.S. What about one step further? Move-aware algorithms, like std::rotate? What about C++11 algorithm improvements, like return iterator at std::rotate, std::fill_n, like std::partition for Forward iterators/ranges? ( by the way, just reported bug about boost::partition https://svn.boost.org/trac/boost/ticket/8927 ) -- Evgeny Panasyuk
Given a user define types that specializes std::swap but isn't moveable (a reasonable scenario for C++03 code still being compiled with a C++03 compiler), wouldn't this change result in 3 copies instead of a single call to the specialized std:swap?
2013/7/29 Joseph Gauterin
Given a user define types that specializes std::swap but isn't moveable (a reasonable scenario for C++03 code still being compiled with a C++03 compiler), wouldn't this change result in 3 copies instead of a single call to the specialized std:swap?
You are right! I've tried to apply patch and run regression tests on my own PC. Different versions of patch break different use cases: std::swap specialization in std namespace, ADL for the users namespaces, ADL for boost namespace... Looks like the only solution that does not break existing code would be to specialize the boost::swap for ::boost::rv<T> and advice users to write constructions like this: boost::swap(boost::move(object1), boost::move(object2)); But that's an ugly solution. Or am I missing something and there is a better way to make the boost::swap function work with emulated rvalue references? -- Best regards, Antony Polukhin
On Mon, 29 Jul 2013, Joseph Gauterin wrote:
Given a user define types that specializes std::swap but isn't moveable (a reasonable scenario for C++03 code still being compiled with a C++03 compiler), wouldn't this change result in 3 copies instead of a single call to the specialized std:swap?
The recommended way is to overload swap for your type, not specialize std::swap. As long as that case still works, the rest might be acceptable... -- Marc Glisse
2013/7/30 Marc Glisse
On Mon, 29 Jul 2013, Joseph Gauterin wrote:
Given a user define types that specializes std::swap but isn't moveable (a
reasonable scenario for C++03 code still being compiled with a C++03 compiler), wouldn't this change result in 3 copies instead of a single call to the specialized std:swap?
The recommended way is to overload swap for your type, not specialize std::swap. As long as that case still works, the rest might be acceptable...
I'd rather spend a few more days thinking of some other solutions. Silently breaking user code to make some c++11-emulation-for-old-compilers work out of the box is not good. Is there a better idea than specializing the boost::swap for ::boost::rv<T> types and forcing users to write `boost::swap(boost::move(object1), boost::move(object2));` ? -- Best regards, Antony Polukhin
The recommended way is to overload swap for your type, not specialize std::swap. As long as that case still works, the rest might be acceptable...
At the time boost::swap was created, my motivating use case involved use of
multiple 3rd party libraries. Some provided swap through ADL, others by
specialising std::swap. Both techniques are legal and there's no clear
technical advantage to either (I prefer the ADL solution since I find code
that opens the std namespace to look 'wrong' - but that's a matter of
taste).
I'm not at all keen on users upgrading from boost 1.38.0-1.54.0 to a newer
version and finding that their O(1) swap has turned into 3 calls to an O(n)
copy because the author of a library they depend on used a technique which
has since fallen out favour due to a consensus forming around the
alternative.
Joe
On Tue, Jul 30, 2013 at 8:51 AM, Marc Glisse
On Mon, 29 Jul 2013, Joseph Gauterin wrote:
Given a user define types that specializes std::swap but isn't moveable (a
reasonable scenario for C++03 code still being compiled with a C++03 compiler), wouldn't this change result in 3 copies instead of a single call to the specialized std:swap?
The recommended way is to overload swap for your type, not specialize std::swap. As long as that case still works, the rest might be acceptable...
-- Marc Glisse
______________________________**_________________ Unsubscribe & other changes: http://lists.boost.org/** mailman/listinfo.cgi/boosthttp://lists.boost.org/mailman/listinfo.cgi/boost
on Tue Jul 30 2013, Joseph Gauterin
The recommended way is to overload swap for your type, not specialize std::swap. As long as that case still works, the rest might be acceptable...
At the time boost::swap was created, my motivating use case involved use of multiple 3rd party libraries. Some provided swap through ADL, others by specialising std::swap. Both techniques are legal and there's no clear technical advantage to either
That's not true. Specializing has at least two serious technical disadvantages: 1. Doesn't work for templates because you can't partially specialize functions 2. Interacts badly with overloads: overload resolution doesn't consider specializations; they're merely implementation substitutions that are made *after* the overload to call has been selected. -- Dave Abrahams
participants (5)
-
Antony Polukhin
-
Dave Abrahams
-
Evgeny Panasyuk
-
Joseph Gauterin
-
Marc Glisse