From: Niels Dekker - no return address on
[ 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
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
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
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
>> 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! ]