[swap] please update documentation with the header I need to include

Thorsten Ottosen wrote:
please update documentation with the header I need to include
I agree, and I do think the documentation at libs/utility/swap.html could be further improved by adding a little example. E.g., #include <boost/swap.hpp> template <typename T> void do_some_generic_work(T& arg1, T& arg2) { // .... boost::swap(arg1, arg2); // .... } IMO such a simple example would suggest the proper use of boost::swap. The utility is especially useful within a generic context. But it's not recommended to do an unqualified call to boost::swap: std::string a1[42]; std::string a2[42]; boost::swap(a1, a2); // Okay. using boost::swap; swap(a1, a2); // Does not compile! It's also not recommended to explicitly specify the template arguments passed to boost::swap. The fact that boost::swap has two template arguments, instead of one, should be considered an implementation detail. (Both arguments must be of the same type anyway.) Just my 2 cents, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

Hi Niels,
[It's] not recommended to do an unqualified call to boost::swap:
std::string a1[42]; std::string a2[42];
boost::swap(a1, a2); // Okay.
using boost::swap; swap(a1, a2); // Does not compile!
why do you think this code won't compile? As far as I can tell, ADL would resolve the call to invoke std::swap(). In fact, ADL is the very reason why some people recommend the exact opposite of what you've been saying, i.e. swap() should always be called unqualified. Take care, Peter

Peter Simons skrev:
Hi Niels,
[It's] not recommended to do an unqualified call to boost::swap:
std::string a1[42]; std::string a2[42];
boost::swap(a1, a2); // Okay.
using boost::swap; swap(a1, a2); // Does not compile!
why do you think this code won't compile?
Maybe the call to swap is ambigious in this case. It could be either boost::swap or std::swap. -Thorsten

2009/6/29 Peter Simons <simons@cryp.to>:
Hi Niels,
> [It's] not recommended to do an unqualified call to boost::swap: > > std::string a1[42]; > std::string a2[42]; > > boost::swap(a1, a2); // Okay. > > using boost::swap; > swap(a1, a2); // Does not compile!
why do you think this code won't compile? As far as I can tell, ADL would resolve the call to invoke std::swap().
Try it. std::swap can't swap arrays, boost::swap can. boost::swap will also call swap via. ADL when appropriate and supports compilers that don't support ADL. Which is why it's recommended that 'boost::swap' is used. Daniel

Daniel James writes:
[It's] not recommended to do an unqualified call to boost::swap:
std::string a1[42]; std::string a2[42];
boost::swap(a1, a2); // Okay.
using boost::swap; swap(a1, a2); // Does not compile!
why do you think this code won't compile? As far as I can tell, ADL would resolve the call to invoke std::swap().
Try it.
| $ cat >test.cpp <<EOF | #include <string> | #include <boost/swap.hpp> | | int main(int, char * []) | { | std::string a1[42]; | std::string a2[42]; | | boost::swap(a1, a2); // Okay. | | using boost::swap; | swap(a1, a2); // Does not compile! | | return 0; | } | EOF | $ g++ -pedantic test.cpp && ./a.out && echo okay | okay Peter

Daniel James wrote:
Try it. std::swap can't swap arrays, boost::swap can. boost::swap will also call swap via. ADL when appropriate and supports compilers that don't support ADL. Which is why it's recommended that 'boost::swap' is used.
Thanks, Daniel. In fact, proper performance of boost::swap /does/ depend on compilers having implemented ADL. But we've found out that for some compilers (including MSVC 7.1, Borland 5.9.3, and Intel 8.1), ADL only works fine when a using-directive ("using namespace std") is used, instead of a using-declaration ("using std::swap"). Luckily this using-directive is hidden within an internal helper function of boost::swap. Peter Simons wrote:
$ cat >test.cpp <<EOF #include <string> #include <boost/swap.hpp>
int main(int, char * []) { std::string a1[42]; std::string a2[42];
boost::swap(a1, a2); // Okay.
using boost::swap; swap(a1, a2); // Does not compile!
return 0; } EOF $ g++ -pedantic test.cpp && ./a.out && echo okay okay
Interesting! Can you tell us whether it picks std::swap or boost::swap? BTW, support for built-in arrays is added to std::swap very recently; it's in the Working Draft. Basically it's my very first (very) little contribution to the Standard :-) 25.4.3 Swap [alg.swap] (www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2914.pdf) says: template<ValueType T, size_t N> requires Swappable<T> void swap(T (&a)[N], T (&b)[N]); 2 Effects: swap_ranges(a, a + N, b) I wonder if GCC has already implemented this new feature. -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

| $ cat >test.cpp <<EOF | #include <string> | #include <boost/swap.hpp> | | int main(int, char * []) | { | std::string a1[42]; | std::string a2[42]; | | boost::swap(a1, a2); // Okay. | | using boost::swap; | swap(a1, a2); // Does not compile! | | return 0; | } | EOF | $ g++ -pedantic test.cpp && ./a.out && echo okay | okay
Can you tell us whether it picks std::swap or boost::swap?
Peter Simons wrote:
It picks boost::swap():
void boost::swap(T1&, T2&) [with T1 = std::string [42], T2 = std::string [42]]
I'm very surprised it doesn't pick std::swap, as found by argument-dependent lookup. What version of GCC are you using exactly? Note that boost::swap is tested extensively <www.boost.org/development/tests/trunk/developer/utility-swap_.html> but /not/ by doing unqualified swap calls, because that's just not the intended usage. Kind regards, Niels

Hi Niels,
I'm very surprised it doesn't pick std::swap, as found by argument-dependent lookup. What version of GCC are you using exactly?
The test program was compiled with g++ 4.4.0 20090526 (prerelease) on ArchLinux/x86. I hope this helps, Peter

I'm very surprised it doesn't pick std::swap, as found by argument-dependent lookup. What version of GCC are you using exactly?
Peter Simons wrote:
The test program was compiled with g++ 4.4.0 20090526 (prerelease) on ArchLinux/x86.
Thanks Peter! It looks like a brandnew GCC bug to me... Can you please confirm that the following simplified version also compiles and runs on your installation of GCC 4.4.0? And if so, does it indeed throw "foo::swap is called"? //////////////////////////////////////// #include <string> #include <algorithm> namespace foo { template<class T1, class T2> void swap(T1&, T2&) { throw "foo::swap is called"; } } int main() { std::string a1[42]; std::string a2[42]; using foo::swap; swap(a1, a2); } //////////////////////////////////////// So far, I've tried Comeau C/C++ 4.3.10.1 (online at www.comeaucomputing.com/tryitout), MSVC 2008 SP1, gcc-4 (GCC) 4.3.2 20080827 (beta) 2 within cygwin, and g++ 4.1.2 at http://codepad.org/76xnAQ7n None of them pick foo::swap. Instead, all of them yield a compile error, trying to call std::swap. Kind regards, Niels

Hi Niels, I hope you don't mind me interjecting. We use the stlport std library with gcc 4.4.0 so I thought I'd add info about that to the thread. Niels Dekker wrote on 29/06/2009 18:33:18:
Re: [boost] [swap] please update documentation...
I'm very surprised it doesn't pick std::swap, as found by argument-dependent lookup. What version of GCC are you using exactly?
Peter Simons wrote:
The test program was compiled with g++ 4.4.0 20090526 (prerelease) on ArchLinux/x86.
Thanks Peter! It looks like a brandnew GCC bug to me... Can you please
confirm that the following simplified version also compiles and runs on your installation of GCC 4.4.0? And if so, does it indeed throw "foo::swap is called"?
I tried the above with gcc 4.4.0 and stlport. It chose std::swap (stlport's) via ADL and failed to compile due to 'invalid array assignment' as expected. It seems that the issue is with gcc 4.4.0's latest standard library rather than a broken ADL or other such detail. Looks like the latest gcc std::swap supports c-style array swapping. #---------- GCC 4.4.0 + STLport 5.1.3 ------------ g++ swap.cpp swap.cpp:19: instantiated from here .../STLport-5.1.3-native/stlport/stl/_algobase.h:93: error: invalid array assignment #---------- GCC 4.4.0 + libstdc++ 4.4.0 ----------- CPLUS_INCLUDE_PATH= g++ swap.cpp ./a.out # no exception is thrown -- it's picking std::swap #---------- GCC 4.2.3 + libstdc++ 4.2.3 ------------ CPLUS_INCLUDE_PATH= g++-4.2.3 swap.cpp swap.cpp:19: instantiated from here ../include/c++/4.2.3/bits/stl_algobase.h:100: error: invalid array assignment #---------- GCC 4.4.0 + libstdc++ 4.4.0 ----------- The following compiles fine with 4.4.0 std library. Switch to stlport headers and it fails to compile as expected. CPLUS_INCLUDE_PATH= g++ -xc++ - << EOF #include <string> #include <algorithm> int main() { std::string a[42], b[42]; std::swap(a, b); } EOF #---------------------------------------- Does the C++0x library allow for std::swap with c-style arrays? If so, maybe the issue is that g++ is implementing it without needing you to specify --std=c++0x. I guess it is not breaking any existing use of std::swap -- just making a missing case work (?) Just to check that it actually is swapping I changed the body of the last snippet to: std::string a[42] = { "a", }, b[42] = { "b", }; std::swap(a, b); return a[0][0] - 'a'; and it did indeed swap. The return code was 1, not 0 -- so the first string in 'a' after the swap began with char 'b'. Hope this info's useful. Regards Adam ------------------------------------------------------------ This email and any attached files contains company confidential information which may be legally privileged. It is intended only for the person(s) or entity to which it is addressed and solely for the purposes set forth therein. If you are not the intended recipient or have received this email in error please notify the sender by return, delete it from your system and destroy any local copies. It is strictly forbidden to use the information in this email including any attachment or part thereof including copying, disclosing, distributing, amending or using for any other purpose. In addition the sender excludes all liabilities (whether tortious or common law) for damage or breach arising or related to this email including but not limited to viruses and libel. SELEX Communications Limited is a Private Limited Company registered in England and Wales under Company Number 964533 and whose Registered Office is Lambda House, Christopher Martin Rd, Basildon, SS14 3EL. England.

adam.butcher@selex-comms.com wrote:
Hi Niels,
I tried the above with gcc 4.4.0 and stlport. It chose std::swap (stlport's) via ADL and failed to compile due to 'invalid array assignment' as expected. It seems that the issue is with gcc 4.4.0's latest standard library rather than a broken ADL or other such detail. Looks like the latest gcc std::swap supports c-style array swapping.
You are right. bits/algorithmfwd.h contains template <typename _Tp, size_t _Nm> void swap(_Tp (&)[_Nm], _Tp (&)[_Nm]);
#---------- GCC 4.4.0 + STLport 5.1.3 ------------
g++ swap.cpp swap.cpp:19: instantiated from here ..../STLport-5.1.3-native/stlport/stl/_algobase.h:93: error: invalid array assignment
#---------- GCC 4.4.0 + libstdc++ 4.4.0 -----------
CPLUS_INCLUDE_PATH= g++ swap.cpp ../a.out # no exception is thrown -- it's picking std::swap
#---------- GCC 4.2.3 + libstdc++ 4.2.3 ------------
CPLUS_INCLUDE_PATH= g++-4.2.3 swap.cpp swap.cpp:19: instantiated from here .../include/c++/4.2.3/bits/stl_algobase.h:100: error: invalid array assignment
#---------- GCC 4.4.0 + libstdc++ 4.4.0 -----------
The following compiles fine with 4.4.0 std library. Switch to stlport headers and it fails to compile as expected.
CPLUS_INCLUDE_PATH= g++ -xc++ - << EOF #include <string> #include <algorithm>
int main() { std::string a[42], b[42]; std::swap(a, b); } EOF #----------------------------------------
Does the C++0x library allow for std::swap with c-style arrays? If so, maybe the issue is that g++ is implementing it without needing you to specify --std=c++0x. I guess it is not breaking any existing use of std::swap -- just making a missing case work (?)
Just to check that it actually is swapping I changed the body of the last snippet to:
std::string a[42] = { "a", }, b[42] = { "b", }; std::swap(a, b); return a[0][0] - 'a';
and it did indeed swap. The return code was 1, not 0 -- so the first string in 'a' after the swap began with char 'b'.
Hope this info's useful. Regards Adam
BR, Dmitry

Dmitry Goncharov wrote:
adam.butcher@selex-comms.com wrote:
Hi Niels,
I tried the above with gcc 4.4.0 and stlport. It chose std::swap (stlport's) via ADL and failed to compile due to 'invalid array assignment' as expected. It seems that the issue is with gcc 4.4.0's latest standard library rather than a broken ADL or other such detail. Looks like the latest gcc std::swap supports c-style array swapping.
You are right. bits/algorithmfwd.h contains template <typename _Tp, size_t _Nm> void swap(_Tp (&)[_Nm], _Tp (&)[_Nm]);
And bits/move.h contains the implementation // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 809. std::swap should be overloaded for array types. template<typename _Tp, size_t _Nm> inline void swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) { for (size_t __n = 0; __n < _Nm; ++__n) swap(__a[__n], __b[__n]); }
#---------- GCC 4.4.0 + STLport 5.1.3 ------------
g++ swap.cpp swap.cpp:19: instantiated from here ..../STLport-5.1.3-native/stlport/stl/_algobase.h:93: error: invalid array assignment
#---------- GCC 4.4.0 + libstdc++ 4.4.0 -----------
CPLUS_INCLUDE_PATH= g++ swap.cpp ../a.out # no exception is thrown -- it's picking std::swap
#---------- GCC 4.2.3 + libstdc++ 4.2.3 ------------
CPLUS_INCLUDE_PATH= g++-4.2.3 swap.cpp swap.cpp:19: instantiated from here .../include/c++/4.2.3/bits/stl_algobase.h:100: error: invalid array assignment
#---------- GCC 4.4.0 + libstdc++ 4.4.0 -----------
The following compiles fine with 4.4.0 std library. Switch to stlport headers and it fails to compile as expected.
CPLUS_INCLUDE_PATH= g++ -xc++ - << EOF #include <string> #include <algorithm>
int main() { std::string a[42], b[42]; std::swap(a, b); } EOF #----------------------------------------
Does the C++0x library allow for std::swap with c-style arrays? If so, maybe the issue is that g++ is implementing it without needing you to specify --std=c++0x. I guess it is not breaking any existing use of std::swap -- just making a missing case work (?)
Just to check that it actually is swapping I changed the body of the last snippet to:
std::string a[42] = { "a", }, b[42] = { "b", }; std::swap(a, b); return a[0][0] - 'a';
and it did indeed swap. The return code was 1, not 0 -- so the first string in 'a' after the swap began with char 'b'.
Hope this info's useful. Regards Adam
BR, Dmitry _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Adam Butcher wrote:
I tried the above with gcc 4.4.0 and stlport. It chose std::swap (stlport's) via ADL and failed to compile due to 'invalid array assignment' as expected. It seems that the issue is with gcc 4.4.0's latest standard library rather than a broken ADL or other such detail. Looks like the latest gcc std::swap supports c-style array swapping.
Thanks very much. Dmitry Goncharov wrote:
You are right. bits/algorithmfwd.h contains template <typename _Tp, size_t _Nm> void swap(_Tp (&)[_Nm], _Tp (&)[_Nm]);
Cool! But still I'm concerned about the results from Peter Simons, compiled with g++ 4.4.0 20090526 (prerelease). As that particular version appears to pick boost::swap, instead of std::swap. The implementation of boost::swap depends on compilers preferring std::swap<T>(T&,T&) over boost::swap<T1,T2>(T1&,T2&), in case of an unqualified swap function call. Thereby, ambiguity is avoided, as was suggested by Steven Watanabe. I really hope this will still work on the latest version of GCC. Adam and Peter, could you please also test the following on g++ 4.4.0? I really hope it compiles! //////////////////////////////////////// namespace foo // "boost" { template<class T1, class T2> void swap(T1&, T2&) { // Trigger a compile error. int staticAssert[sizeof(T1)!=sizeof(T2)] = {1}; } } namespace bar // "std" { template<class T> void swap(T&, T&) { return; // okay. } class string {}; } int main() { bar::string a1[42]; bar::string a2[42]; using foo::swap; swap(a1, a2); } //////////////////////////////////////// At least, it does compile on g++ 4.1.2, at http://codepad.org/0lyaPrym Kind regards, Niels

Niels Dekker - address until 2010-10-10 wrote:
Cool! But still I'm concerned about the results from Peter Simons, compiled with g++ 4.4.0 20090526 (prerelease). As that particular version appears to pick boost::swap, instead of std::swap.
The implementation of boost::swap depends on compilers preferring std::swap<T>(T&,T&) over boost::swap<T1,T2>(T1&,T2&), in case of an unqualified swap function call. Thereby, ambiguity is avoided, as was suggested by Steven Watanabe. I really hope this will still work on the latest version of GCC.
Adam and Peter, could you please also test the following on g++ 4.4.0? I really hope it compiles!
////////////////////////////////////////
namespace foo // "boost" { template<class T1, class T2> void swap(T1&, T2&) { // Trigger a compile error. int staticAssert[sizeof(T1)!=sizeof(T2)] = {1}; } }
namespace bar // "std" { template<class T> void swap(T&, T&) { return; // okay. }
class string {}; }
int main() { bar::string a1[42]; bar::string a2[42];
using foo::swap; swap(a1, a2); }
////////////////////////////////////////
At least, it does compile on g++ 4.1.2, at http://codepad.org/0lyaPrym Kind regards, Niels
Any of gcc-4.4.0, gcc-4.3.4 or gcc-4.2.4 compiles this program. BR, Dmitry

Hi Niels,
Adam and Peter, could you please also test the following on g++ 4.4.0?
the program compiles fine, which made me wonder about my earlier report that gcc 4.4.0 would choose boost::swap in the example program we previously talked about. So I tried to repeat my finding. I edited an std::cout << __PRETTY_FUNCTION__ << std::endl;" into <boost/utility/swap.hpp>, compiled the following program, and ran it: #include <iostream> #include <string> #include <boost/swap.hpp> int main(int, char * []) { std::string a1[42]; std::string a2[42]; boost::swap(a1, a2); // Okay. using boost::swap; swap(a1, a2); // Does not compile! return 0; } Surely enough, the output is g++ -pedantic test.cpp && ./a.out void boost::swap(T1&, T2&) [with T1 = std::string [42], T2 = std::string [42]] ..., just like last time but then I looked real hard at the source code and finally noticed that the program calls boost::swap() explicitly, too, which is where that debug output comes from. In other words, I was wrong: gcc 4.4.0 does *not* pick boost::swap by ADL in this example. I'm sorry for causing confusion. Take care, Peter

Peter Simons wrote:
In other words, I was wrong: gcc 4.4.0 does *not* pick boost::swap by ADL in this example.
I'm sorry for causing confusion.
No problem, thanks for your reply. I'm glad GCC 4.4.0 does it correctly. Kind regards, Niels

I'm working with the Multicast receiver example at: http://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio/example/multicast/r... Notice that you specify the listen_address as you create the endpoint that is bound to the socket. Later when you call socket::set_option with the multicast_address, I would expect the listen_address to be honored. The current implementation uses INET_ANY for the interface in the multicast subscription. This means the multicast messages may arrive on one interface while you are listening for them on another one. I can't think of any case in which you would want to specify an IP for the receive, but not for the join_group. Workaround: There is a different constructor for the join_group object that does produce the desired behavior, but it is not obvious that you should need it. Also it does not accept boost::asio::ip::addresses as arguments (which would make sense) but requires that you "convert" them to ip4 (or ip6) addresses. Seems awkward. Dale

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Monday 29 June 2009, Peter Simons wrote:
Hi Niels,
[It's] not recommended to do an unqualified call to boost::swap:
std::string a1[42]; std::string a2[42];
boost::swap(a1, a2); // Okay.
using boost::swap; swap(a1, a2); // Does not compile!
why do you think this code won't compile? As far as I can tell, ADL would resolve the call to invoke std::swap(). In fact, ADL is the very reason why some people recommend the exact opposite of what you've been saying, i.e. swap() should always be called unqualified.
They recommend that swap be called unqualified and ADL used in the context of working around the limitations of std::swap. boost::swap on the other hand handles the ADL internally. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpI0xoACgkQ5vihyNWuA4W91QCgz4XGn+jpGf3GUSN0u4K9NUAZ cm0AoJRs/ghIj8Be+QoLsCeSj6gYxsdc =8AkT -----END PGP SIGNATURE-----
participants (8)
-
adam.butcher@selex-comms.com
-
Dale Wilson
-
Daniel James
-
Dmitry Goncharov
-
Frank Mori Hess
-
Niels Dekker - address until 2010-10-10
-
Peter Simons
-
Thorsten Ottosen