|
Prev: recommendation for second C++ book? (not a generic request)
Next: Class & Instance thereof having same Name.
From: Niels Dekker - no return address on 8 Apr 2008 04:43 [ Sorry for my delayed response -- I was at the ACCU conference! ] Alberto Ganesh Barbati wrote: > Someone suggested this idiom: > using std::swap; > swap(x, y); > which does the right thing in all cases, but, frankly... it sucks! I'd rather call it a clever trick :-) BTW, the idiom is recommended by Scott Meyers, Effective C++ Third Edition, item 25. Note that Joseph Gauterin has added a function template, boost::swap, to Boost's sandbox, to wrap this idiom: http://svn.boost.org/trac/boost/browser/sandbox/swap/boost/utility/swap.hpp Yechezkel Mett wrote: > namespace std > { > auto concept Swappable<typename T> { > void swap(T& lhs, T& rhs) > { > T x(std::move(lhs)); > lhs = std::move(rhs); > rhs = std::move(x); > } > }; > > auto concept MemberSwappable<typename T> { > void T::swap(T&); > }; > > template<MemberSwappable T> > concept_map Swappable<T> { > swap(T& lhs, T& rhs) > { > lhs.swap(rhs); > } > }; > > template <Swappable T> > void swap(T&& a, T&& b) > { > Swappable<T>::swap(a, b); > } > } Looks nice to me. Still... when following your suggested approach, would it be okay for a user to implement member swap by doing std::swap? I fear infinite recursion!!! class A { int data; public: void swap(A& arg) { std::swap(*this, arg); // Infinite loop? } }; Anyway, I'm glad that your suggested approach supports swapping temporaries of *any* Swappable type (including built-in types and non-std user defined types), which is the point I was trying to make. :-) Kind regards, Niels -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alberto Ganesh Barbati on 9 Apr 2008 08:57 Niels Dekker - no return address ha scritto: > [ Sorry for my delayed response -- I was at the ACCU conference! ] > > Alberto Ganesh Barbati wrote: >> Someone suggested this idiom: >> using std::swap; >> swap(x, y); >> which does the right thing in all cases, but, frankly... it sucks! > > I'd rather call it a clever trick :-) BTW, the idiom is recommended by Scott > Meyers, Effective C++ Third Edition, item 25. Note that Joseph Gauterin has > added a function template, boost::swap, to Boost's sandbox, to wrap this > idiom: > http://svn.boost.org/trac/boost/browser/sandbox/swap/boost/utility/swap.hpp I knew that this is the "recommended way". However, I do believe it is the recommended way simply because there's actually no other viable option in the current language and not because it is an inherently good idiom. Whenever the issue is to provide "extension points" to algorithm, I believe that concepts and concept maps provide a much better idiom than relying on ADL-reachable free functions, so I am expecting "recommendations" to change with the advent of C++0x. > Yechezkel Mett wrote: >> namespace std >> { >> auto concept Swappable<typename T> { >> void swap(T& lhs, T& rhs) >> { >> T x(std::move(lhs)); >> lhs = std::move(rhs); >> rhs = std::move(x); >> } >> }; >> >> auto concept MemberSwappable<typename T> { >> void T::swap(T&); >> }; >> >> template<MemberSwappable T> >> concept_map Swappable<T> { >> swap(T& lhs, T& rhs) >> { >> lhs.swap(rhs); >> } >> }; >> >> template <Swappable T> >> void swap(T&& a, T&& b) >> { >> Swappable<T>::swap(a, b); >> } >> } > > Looks nice to me. Still... when following your suggested approach, would it be > okay for a user to implement member swap by doing std::swap? I fear infinite > recursion!!! > > class A > { > int data; > public: > void swap(A& arg) { > std::swap(*this, arg); // Infinite loop? > } > }; It's good that you've pointed that out. Given a more precise definition what std::swap() does in line with: "Apply the first applicable algorithm in the following list: 1) a concept_map provided implementation 2) the swap member 3) an ADL-reacheable free function swap() 4) a default implementation relying on MoveConstructible/MoveAssignable" then it is clear than none of the extension points can be implemented in terms of std::swap() itself on the whole object (calling std::swap() on subobjects is allowed, of course). I agree that this might break existing code, like the one you shown. Do you reckon that such idiom is so common that deserves to be preserved? Ganesh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Niels Dekker - no return address on 12 Apr 2008 03:11 Alberto Ganesh Barbati wrote: >>> Someone suggested this idiom: >>> using std::swap; >>> swap(x, y); .... > I knew that this is the "recommended way". However, I do believe it is > the recommended way simply because there's actually no other viable > option in the current language and not because it is an inherently good > idiom. Whenever the issue is to provide "extension points" to algorithm, > I believe that concepts and concept maps provide a much better idiom > than relying on ADL-reachable free functions Okay, so far I agree :-) >>I fear infinite recursion!!! >> >> class A >> { >> int data; >> public: >> void swap(A& arg) { >> std::swap(*this, arg); // Infinite loop? >> } >> }; > > It's good that you've pointed that out. Given a more precise definition > what std::swap() does in line with: "Apply the first applicable > algorithm in the following list: > > 1) a concept_map provided implementation > 2) the swap member > 3) an ADL-reacheable free function swap() > 4) a default implementation relying on MoveConstructible/MoveAssignable" > > then it is clear than none of the extension points can be implemented in > terms of std::swap() itself on the whole object (calling std::swap() on > subobjects is allowed, of course). > > I agree that this might break existing code, like the one you shown. Do > you reckon that such idiom is so common that deserves to be preserved? I don't know if it's common, but it looks quite reasonable to me, writing a swap member by calling std::swap on the whole object. So I'd rather not have this valid piece of C++03 *silently* turn into infinite recursion, when upgrading to C++0x. Actually I just thought of another use case! I just suggested adding a swap member function to boost::optional<T> at the Boost developer mailing list ("Re: [boost] [optional] problems with swap()"), to be implemented as follows: void swap( optional & arg ) { using std::swap; swap(*this, arg); } Doing so would allow an end user to customize the behavior of optional<T>::swap for her specific type T, by providing a custom swap(optional<T>&, optional<T>&) function, either in the boost namespace, the std namespace, or the namespace of T. This would be relevant because the currently provided boost::swap(optional<T>&, optional<T>&) can be quite expensive, depending on the type T. (This is the main subject of the Boost developer mailing list discussion, as started by Thorsten Ottosen.) The user might get better performance and exception guarantees by customizing swap(optional<T>&, optional<T>&) for her type T. And she would certainly appreciate having the optional<T>::swap member function call her customized swap. Don't you think? BTW, I wonder what would happen when calling your proposed std::swap for a type that has a non-public swap member function... Would it try to call the member function (causing a compile error), or would it consider the type to be non-MemberSwappable? Kind regards, Niels -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alberto Ganesh Barbati on 12 Apr 2008 15:43 Niels Dekker - no return address ha scritto: > > Actually I just thought of another use case! I just suggested adding a > swap member function to boost::optional<T> at the Boost developer > mailing list ("Re: [boost] [optional] problems with swap()"), to be > implemented as follows: > > void swap( optional & arg ) > { > using std::swap; > swap(*this, arg); > } > > Doing so would allow an end user to customize the behavior of > optional<T>::swap for her specific type T, by providing a custom > swap(optional<T>&, optional<T>&) function, either in the boost > namespace, the std namespace, or the namespace of T. This would be > relevant because the currently provided boost::swap(optional<T>&, > optional<T>&) can be quite expensive, depending on the type T. (This is > the main subject of the Boost developer mailing list discussion, as > started by Thorsten Ottosen.) The user might get better performance and > exception guarantees by customizing swap(optional<T>&, optional<T>&) for > her type T. And she would certainly appreciate having the > optional<T>::swap member function call her customized swap. Don't you > think? She could easily do that by providing a concept map like this: concept_map std::Swappable<boost::optional<MyType>> { void swap(boost::optional<MyType>& a, boost::optional<MyType>& b) { // implementation here } }; that's because an explicit concept_map would have precedence above all other ways of implementing std::swap. > BTW, I wonder what would happen when calling your proposed std::swap for > a type that has a non-public swap member function... Would it try to > call the member function (causing a compile error), or would it consider > the type to be non-MemberSwappable? My understanding of concepts is very limited and I could not find an authoritative answer in paper N2501. I hope someone more knowledgeable will answer this question, as I am curious about it too. Ganesh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Niels Dekker - no return address on 13 Apr 2008 03:47 >> I just suggested adding a swap member function to boost::optional<T> >> at the Boost developer mailing list ("Re: [boost] [optional] problems >> with swap()"), to be implemented as follows: >> >> void swap( optional & arg ) >> { >> using std::swap; >> swap(*this, arg); >> } >> Doing so would allow an end user to customize the behavior of >> optional<T>::swap for her specific type T, by providing a custom >> swap(optional<T>&, optional<T>&) function, either in the boost >> namespace, the std namespace, or the namespace of T. Alberto Ganesh Barbati wrote: > She could easily do that by providing a concept map like this: > > concept_map std::Swappable<boost::optional<MyType>> > { > void swap(boost::optional<MyType>& a, boost::optional<MyType>& b) > { > // implementation here > } > }; Cool! I guess one would need to change the implementation of the boost::optional<T>::swap member function, to directly call your std::swap: void swap( optional & arg ) { // Calling the new C++0x std::swap by Barbati & Mett: std::swap(*this, arg); } My previous version (doing "using std::swap") would do ADL, and find boost::swap(optional<T>&, optional<T>&), thereby bypassing your concept_map. >> BTW, I wonder what would happen when calling your proposed std::swap for >> a type that has a non-public swap member function... Would it try to >> call the member function (causing a compile error), or would it consider >> the type to be non-MemberSwappable? > > My understanding of concepts is very limited and I could not find an > authoritative answer in paper N2501. I hope someone more knowledgeable > will answer this question, as I am curious about it too. I really hope that a class that has a non-public swap member function will be considered non-MemberSwappable. Anyway, you should definitely try ConceptGCC! :-) Please note that it still has some issue regarding access to non-public members: Ticket #22, "Concept maps should not be able to access private data", http://svn.osl.iu.edu/trac/conceptgcc/ticket/22 Kind regards, Niels -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Next
|
Last
Pages: 1 2 Prev: recommendation for second C++ book? (not a generic request) Next: Class & Instance thereof having same Name. |