Topic: Should std::swap be disabled by an explicit copy constructor?


Author: dave@boost-consulting.com (David Abrahams)
Date: Sun, 5 Nov 2006 03:16:02 GMT
Raw View
thorsten.ottosen@dezide.com (Thorsten Ottosen) writes:

> David Abrahams wrote:
>> Thorsten Ottosen <thorsten.ottosen@dezide.com> writes:
>
>>>I vaguely remember that eg. the std::sort() requires a non-throwing
>>> swap(),
>>
>>
>> It doesn't.
>>
>>
>>>but I couldn't find that in the standard anywhere.
>>>
>>>However if that is not a requirement, then how can such an algorithm
>>>guarantee that no elements disappears in case of an exception during
>>> swap().
>>
>>
>> It doesn't.  sort never made a guarantee that no element disappears in
>> the event of an exception, whether from swap, assignment, copy
>> construction, or comparison.
>
> And therefore my point that a non-throwing swap is better than one
> that throws.

There's no relation.  sort is not required to use swap.  Even if swap
doesn't throw, sort might still have that behavior.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Niels Dekker - no return address <unknown@this.is.invalid>
Date: Sun, 5 Nov 2006 22:59:46 CST
Raw View
David Abrahams wrote:
> sort is not required to use swap.

Shouldn't it use swap?  Because isn't swap a point of customization?

In N1691, Explicit Namespaces, you wrote:
  A point of customization is a procedure (like swap) whose
  implementation might be supplied or refined by clients for
  specific types, and that is used by a library component
  (like sort).
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1691.html


Thanks in advance,

Niels Dekker
C++ programmer at LKEB, Leiden University Medical Center

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: thorsten.ottosen@dezide.com (Thorsten Ottosen)
Date: Mon, 6 Nov 2006 17:24:18 GMT
Raw View
Niels Dekker - no return address wrote:
> David Abrahams wrote:
>
>>sort is not required to use swap.
>
>
> Shouldn't it use swap?  Because isn't swap a point of customization?
>

It's not required to AFAIR. High quality implementations like metrowerks
'do use swap().

-Thorsten

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: unknown@this.is.invalid (Niels Dekker - no return address)
Date: Tue, 31 Oct 2006 23:52:44 GMT
Raw View
Thorsten Ottosen wrote about the purpose of an explicit copy
constructor:
> well, it avoids slicing in pass by value situations.

Oops, I hadn't realized that!  Actually, the compiler I'm currently
using doesn't seem to realize it either, as it allows me to pass Foo
objects with an explicit copy ctor by value:
//////////////////////////////////////////////////////////////////////
  class Foo
  {
    int m_data;
  public:
    Foo() {};
    explicit Foo(const Foo& rhs) : m_data(rhs.m_data) {};
  };

  void PassFooByValue(Foo arg)
  {
    Foo localVar(arg);
  }

  int main()
  {
    Foo foo;
    PassFooByValue(foo);  // Ill-formed?
  }
//////////////////////////////////////////////////////////////////////
I guess it's just a bug in that particular compiler I'm currently
using...  www.dinkumware.com/exam and www.comeaucomputing.com showed
me that other compilers do reject the call PassFooByValue(foo).

Thorsten Ottosen:
>> Okay, but I still might want to protect the users of my class from
>> accidentally calling std::swap, especially if the assignment of my class
>> might throw an exception.
>
> why do you want to prohibit that?

In some cases I would like to prevent users from applying certain
functions onto objects of my class.  You know it's common practice,
for instance, to disable the assignment, or the copy constructor,
whenever those are inappropriate.  Why not disable the swap function
for those classes whose objects don't need to be swapped?  Especially
because if my class has a throwing assignment, an accidental call to
std::swap might cause a lot of troubles, from the client's
perspective!  Another reason to prevent calls to std::swap is because
you have a class template that has its own swap function.  Some users
(or some older std library implementations) might still accidentally
try to call std::swap for your class template.  Wouldn't you like to
be able to prevent that from happening?


Alberto Ganesh Barbati wrote:
> I feel that using the explicit copy constructor to disable swap is just
> too hackish...

Okay, I agree that declaring the copy ctor explicit isn't always the
most appropriate way to disable swap...

> However, I concede that your proposal has value because it tries to
> clarify what happens if the copy constructor is explicit.

Thanks  :-)

> About the specific wording you propose, I see two problems:
>
> 1) imposing the requirement on swap, implicitly imposes the same
> requirement on all specializations and this may be undesirable. I would
> specify that the requirement applies only on the default implementation.

Interesting...  I surely meant my suggestion ("The program is
ill-formed if type T has an explicit copy constructor") to apply only
for the default implementation of std::swap, not for any
specialization.

Do you mean to say that the current specification of std::swap is
applicable to any user supplied specialization as well?  I mean, is a
program ill-formed if it has a std::swap specialization for a
non-assignable type?  Or if it has a std::swap specialization that
does not exchanges any values?


> 2) what happens if T has more than one copy constructor?
[...]
> Moreover, you have to consider that if r-value references are introduced
> in the language, the whole thing about swapping might be revised. For
> example the use of move constructors instead of copy constructor might
> be conceivable. I would wait until the situation is settled before
> attempting to amend std::swap.

Thanks for your input!

--
Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
C++ programmer at LKEB, Leiden University Medical Center

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: thorsten.ottosen@dezide.com (Thorsten Ottosen)
Date: Wed, 1 Nov 2006 20:09:29 GMT
Raw View
David Abrahams wrote:
> Thorsten Ottosen <thorsten.ottosen@dezide.com> writes:

>>I vaguely remember that eg. the std::sort() requires a non-throwing
>>swap(),
>
>
> It doesn't.
>
>
>>but I couldn't find that in the standard anywhere.
>>
>>However if that is not a requirement, then how can such an algorithm
>>guarantee that no elements disappears in case of an exception during
>>swap().
>
>
> It doesn't.  sort never made a guarantee that no element disappears in
> the event of an exception, whether from swap, assignment, copy
> construction, or comparison.

And therefore my point that a non-throwing swap is better than one that
throws.

-Thorsten

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Thu, 26 Oct 2006 18:20:19 GMT
Raw View
Thorsten Ottosen ha scritto:
> Niels Dekker - no return address wrote:
>> A careful programmer might want to disable std::swap for her class,
>> e.g., because her class has a throwing assignment. Now it seems that
>> disabling std::swap is achieved by declaring the copy constructor of
>> this class explicit!
>=20
> swap() is funny beast and actually presents two interfaces.
>=20
> The first is called qualified as in
>=20
>   std::swap(a,b)
>=20
> and this is not IMO intended to be a nothrow operation. OTOH
>=20
>   swap(a,b)
>=20
> looks into other namespaces (via ADL) for a function called swap(), and=
=20
> this should IMO be a nothrow operation.

I believe the intent of the introduction of the Swappable concept in the=20
current draft of the C++ standard is to always prefer the use of=20
unqualified swap() in library code. Can anyone confirm that? The correct=20
way to use swap from outside the std namespace, would be:

   using std::swap;
   swap(a, b);

> this should IMO be a nothrow operation. The latter can eg. be disabled=20
> by calling a private function inside its definition.

That won't work, because it would make the definition of swap=20
ill-formed, so it won't even compile. OTOH, the OP actually wants to=20
make the *use* of swap ill-formed or otherwise diagnosable.

The only way I see to achieve what the OP wants for UDTs is to declare=20
swap but not define it. This can be done either by providing a function=20
in the namespace of the UDT or by specializing std::swap.

Notice that the error will be diagnosed at link time, not at compile=20
time, making the diagnostic less appealing.

There's a small gotcha for class templates. The current standard states=20
that this:

   template <class T> class MyTemplate;

   namespace std
   {
      template<class T>
      void swap(MyTemplate<T>&, MyTemplate<T>&);
   }

calls for undefined behaviour. In fact, the code above is a declaration=20
of an overloaded template, as opposed to the case of UDTs where we had a=20
specialization of an existing template. If I read it correctly,=20
=A717.4.3.1/1 makes the overload illegal while the specialization is=20
legal. So for class templates, the declaration in the namespace of the=20
template is the only viable approach.

HTH,

Ganesh

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Thu, 26 Oct 2006 23:00:09 CST
Raw View
Alberto Ganesh Barbati wrote:
> > Niels Dekker - no return address wrote:
> >> A careful programmer might want to disable std::swap for her class,
> >> e.g., because her class has a throwing assignment. Now it seems that
> >> disabling std::swap is achieved by declaring the copy constructor of
> >> this class explicit!
> > >
> I believe the intent of the introduction of the Swappable concept in the
> current draft of the C++ standard is to always prefer the use of
> unqualified swap() in library code. Can anyone confirm that? The correct
> way to use swap from outside the std namespace, would be:
>
>    using std::swap;
>    swap(a, b);

If a program wishes to adopt the same technique for swapping objects as
the Standard Library's own routines then the above example is the best
match. Whether it is also the "correct" approach however depends
entirely on the needs of the individual C++ program.

> > this should IMO be a nothrow operation. The latter can eg. be disabled
> > by calling a private function inside its definition.
>
> That won't work, because it would make the definition of swap
> ill-formed, so it won't even compile. OTOH, the OP actually wants to
> make the *use* of swap ill-formed or otherwise diagnosable.
>
> The only way I see to achieve what the OP wants for UDTs is to declare
> swap but not define it. This can be done either by providing a function
> in the namespace of the UDT or by specializing std::swap.

The original article provided no information at all about what its
author "wanted". So about the only thing that we should assume is that
he would like an answer to his question :-). And none of this
information about swap() routines and throw clauses, however
interesting it may be, comes at all close to answering the original
question.

And the answer to that question - whether the declaration of an
explicit copy constructor for a type should make objects of that type
incompatible with std::swap()'s default implementation - is not
completely clear.

Nevertheless, one could argue that - since the purpose of an explicit
copy constructor is itself somewhat ill-defined, the fact that the
declaration of one for a type may prevent std::swap() from being used
with objects of that type - is not all that unreasonable a consequence.
After all, the purpose of std::swap() is to exchange two, already
allocated objects. And since the two objects are being exchanged - and
not allocated - the assignment initializer syntax does seem the most
appropriate syntax for std::swap's implementation to employ. And in
light of the fact that an explicit copy constructor expressly prohibits
the assignment initialization syntax for its type - it seems reasonable
that explicit copy constructors and std::swap()'s default
implementation should not mix. Of course, it would be better were the
Standard to state as much - since this line of reasoning is speculative
at this point.

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: unknown@this.is.invalid (Niels Dekker - no return address)
Date: Fri, 27 Oct 2006 21:44:19 GMT
Raw View
Greg Herlihy wrote:
> And the answer to that question - whether the declaration of an
> explicit copy constructor for a type should make objects of that type
> incompatible with std::swap()'s default implementation - is not
> completely clear.
>
> Nevertheless, one could argue that - since the purpose of an explicit
> copy constructor is itself somewhat ill-defined, the fact that the
> declaration of one for a type may prevent std::swap() from being used
> with objects of that type - is not all that unreasonable a consequence.
> After all, the purpose of std::swap() is to exchange two, already
> allocated objects. And since the two objects are being exchanged - and
> not allocated - the assignment initializer syntax does seem the most
> appropriate syntax for std::swap's implementation to employ. And in
> light of the fact that an explicit copy constructor expressly prohibits
> the assignment initialization syntax for its type - it seems reasonable
> that explicit copy constructors and std::swap()'s default
> implementation should not mix. Of course, it would be better were the
> Standard to state as much - since this line of reasoning is speculative
> at this point.

Thank you, Greg!  I fully agree with you!  I must admit I have my own
reasons too.  :-)  I think the notion of an "explicit copy constructor"
will become more meaningful and useful, once it has the impact of
disabling std::swap.  Also, as a "client", I would like to be able to
disable std::swap for some of my classes *and* some of my class
templates, without necessarily disabling their CopyConstructibility or
Assignability.

Thorsten Ottosen wrote:
> swap() is funny beast and actually presents two interfaces.
> The first is called qualified as in
>    std::swap(a,b)
> and this is not IMO intended to be a nothrow operation.

Okay, but I still might want to protect the users of my class from
accidentally calling std::swap, especially if the assignment of my class
might throw an exception.

Alberto Ganesh Barbati wrote:
> The only way I see to achieve what the OP wants for UDTs is to declare
> swap but not define it. This can be done either by providing a function
> in the namespace of the UDT or by specializing std::swap.
>
> Notice that the error will be diagnosed at link time, not at compile
> time, making the diagnostic less appealing.

A good point.  Although it's certainly possible to trigger an error at
compile time, when calling a swap that is declared (but not defined) in
the namespace of a UDT.  Just declare the function as having an
undefined (incomplete) return type!

But let's please return to the original subject!  :-)

The current Working Draft specifies std::swap as follows:
  template<class T> void swap(T& a , T& b );
  1 Requires: Type T is CopyConstructible and Assignable.
  2 Effects: Exchanges values stored in two locations.
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n2009.pdf

I would like to have a line added to the specification of std::swap,
saying: "The program is ill-formed if type T has an explicit copy
constructor."

What do you think?

--
Niels Dekker
C++ programmer at LKEB, Leiden University Medical Center

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Sun, 29 Oct 2006 19:53:08 CST
Raw View
Niels Dekker - no return address wrote:
> The current Working Draft specifies std::swap as follows:
>   template<class T> void swap(T& a , T& b );
>   1 Requires: Type T is CopyConstructible and Assignable.
>   2 Effects: Exchanges values stored in two locations.
> http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n2009.pdf
>
> I would like to have a line added to the specification of std::swap,
> saying: "The program is ill-formed if type T has an explicit copy
> constructor."
>
> What do you think?

I think that your suggestion should be filed as a Standard Library
Defect Report under "Should std::swap be disabled by an explicit copy
constructor?".

Otherwise, as far as I can tell, the class in your original example is
both Assignable and Copy Constructible. So by my reading of the
Standard, std::swap() is obligated to swap the objects. The fact that
std::swap() fails to do so - and fails with every C++ compiler tested -
suggests several possible interpetations of which only one should be
deemed correct:

   1. Standard Library's std::swap() function is apparently universally
broken (conceivable, but unlikely),

   2. A CopyConstructible type shall not have an explicit copy
constructor (possible, but not supported in the current language of the
Standard)

   3. The result of calling std::swap() to exchange two objects whose
copy constructors are declared explicit is (pick one):

         A. unspecified
         B. implementation-defined
         C. undefined
         D. ill-formed (no diagnostic required)
         E. ill-formed

So not only is your suggestion (choice E) the most programmer-friendly
of the lot, it is also the most compiler vendor-friendly choice as
well. Because all that is needed to "resolve" this defect is to have
the Standard ratifiy the current behavior of the majority of C++
compilers in existence.

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: David Abrahams <dave@boost-consulting.com>
Date: Mon, 30 Oct 2006 09:37:47 CST
Raw View
thorsten.ottosen@dezide.com (Thorsten Ottosen) writes:

> swap() is funny beast and actually presents two interfaces.
>
> The first is called qualified as in
>
>   std::swap(a,b)
>
> and this is not IMO intended to be a nothrow operation. OTOH
>
>   swap(a,b)
>
> looks into other namespaces (via ADL) for a function called swap(),
> and this should IMO be a nothrow operation.

On what do you base your opinions about which swap(s) should be
allowed to throw?

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Mon, 30 Oct 2006 17:42:30 GMT
Raw View
AlbertoBarbati@libero.it (Alberto Ganesh Barbati) writes:

> I believe the intent of the introduction of the Swappable concept in
> the current draft of the C++ standard is to always prefer the use of
> unqualified swap() in library code. Can anyone confirm that?

Practically speaking, yes, that's right.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Thorsten Ottosen <thorsten.ottosen@dezide.com>
Date: Mon, 30 Oct 2006 11:46:54 CST
Raw View
Niels Dekker - no return address wrote:
> Greg Herlihy wrote:
>
>>And the answer to that question - whether the declaration of an
>>explicit copy constructor for a type should make objects of that type
>>incompatible with std::swap()'s default implementation - is not
>>completely clear.
>>
>>Nevertheless, one could argue that - since the purpose of an explicit
>>copy constructor is itself somewhat ill-defined,

well, it avoids slicing in pass by value situations.

> Okay, but I still might want to protect the users of my class from
> accidentally calling std::swap, especially if the assignment of my class
> might throw an exception.

why do you want to prohibit that?

> But let's please return to the original subject!  :-)
>
> The current Working Draft specifies std::swap as follows:
>   template<class T> void swap(T& a , T& b );
>   1 Requires: Type T is CopyConstructible and Assignable.
>   2 Effects: Exchanges values stored in two locations.
> http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n2009.pdf
>
> I would like to have a line added to the specification of std::swap,
> saying: "The program is ill-formed if type T has an explicit copy
> constructor."
>

It should IMO be corrected to say "A type with an explicit CC can be
swapped".

-Thorsten

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Mon, 30 Oct 2006 17:47:20 GMT
Raw View
Niels Dekker - no return address ha scritto:
>>
>> Notice that the error will be diagnosed at link time, not at compile
>> time, making the diagnostic less appealing.
>
> A good point.  Although it's certainly possible to trigger an error at
> compile time, when calling a swap that is declared (but not defined) in
> the namespace of a UDT.  Just declare the function as having an
> undefined (incomplete) return type!

Never thought of that! Nice trick. Thanks.

> But let's please return to the original subject!  :-)
>
> The current Working Draft specifies std::swap as follows:
>   template<class T> void swap(T& a , T& b );
>   1 Requires: Type T is CopyConstructible and Assignable.
>   2 Effects: Exchanges values stored in two locations.
> http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2006/n2009.pdf
>
> I would like to have a line added to the specification of std::swap,
> saying: "The program is ill-formed if type T has an explicit copy
> constructor."
>
> What do you think?
>

I feel that using the explicit copy constructor to disable swap is just
too hackish... I don't think the standard should promote this kind of
corner-case programming.

However, I concede that your proposal has value because it tries to
clarify what happens if the copy constructor is explicit.

About the specific wording you propose, I see two problems:

1) imposing the requirement on swap, implicitly imposes the same
requirement on all specializations and this may be undesirable. I would
specify that the requirement applies only on the default implementation.

2) what happens if T has more than one copy constructor? Yes, that can
happen, for example:

  struct A
  {
    A();
    A(A&);  // a copy constructor
    A(const A&); // a copy constructor as well!
  };

(see 12.8/2 for details).

Moreover, you have to consider that if r-value references are introduced
in the language, the whole thing about swapping might be revised. For
example the use of move constructors instead of copy constructor might
be conceivable. I would wait until the situation is settled before
attempting to amend std::swap.

Just my 2 eurocent,

Ganesh

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Thorsten Ottosen <thorsten.ottosen@dezide.com>
Date: Mon, 30 Oct 2006 13:08:09 CST
Raw View
David Abrahams wrote:
> thorsten.ottosen@dezide.com (Thorsten Ottosen) writes:
>
>
>>swap() is funny beast and actually presents two interfaces.
>>
>>The first is called qualified as in
>>
>>  std::swap(a,b)
>>
>>and this is not IMO intended to be a nothrow operation. OTOH
>>
>>  swap(a,b)
>>
>>looks into other namespaces (via ADL) for a function called swap(),
>>and this should IMO be a nothrow operation.
>
>
> On what do you base your opinions about which swap(s) should be
> allowed to throw?

I think of std::swap(a,b) as an algorithm (although a simple one), and
swap(a,b) as the customization point in algorithms.

I vaguely remember that eg. the std::sort() requires a non-throwing
swap(), but I couldn't find that in the standard anywhere.

However if that is not a requirement, then how can such an algorithm
guarantee that no elements disappears in case of an exception during
swap(). (AFAICT, it cannot without a non-throwing assignment, in which
case swap() would be nothrow anyway)?




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Tue, 31 Oct 2006 15:02:27 GMT
Raw View
Thorsten Ottosen <thorsten.ottosen@dezide.com> writes:

> David Abrahams wrote:
>> thorsten.ottosen@dezide.com (Thorsten Ottosen) writes:
>>
>>
>>>swap() is funny beast and actually presents two interfaces.
>>>
>>>The first is called qualified as in
>>>
>>>  std::swap(a,b)
>>>
>>>and this is not IMO intended to be a nothrow operation. OTOH
>>>
>>>  swap(a,b)
>>>
>>>looks into other namespaces (via ADL) for a function called swap(),
>>> and this should IMO be a nothrow operation.
>>
>>
>> On what do you base your opinions about which swap(s) should be
>> allowed to throw?
>
> I think of std::swap(a,b) as an algorithm (although a simple one), and
> swap(a,b) as the customization point in algorithms.

So?

> I vaguely remember that eg. the std::sort() requires a non-throwing
> swap(),

It doesn't.

> but I couldn't find that in the standard anywhere.
>
> However if that is not a requirement, then how can such an algorithm
> guarantee that no elements disappears in case of an exception during
> swap().

It doesn't.  sort never made a guarantee that no element disappears in
the event of an exception, whether from swap, assignment, copy
construction, or comparison.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Niels Dekker - no return address <unknown@this.is.invalid>
Date: Tue, 24 Oct 2006 21:39:32 CST
Raw View
A careful programmer might want to disable std::swap for her class,
e.g., because her class has a throwing assignment. Now it seems that
disabling std::swap is achieved by declaring the copy constructor of
this class explicit!

Indeed, the following program is rejected by all compilers and std
library implementations I tried sofar, including MSVC++ 8.0, GNU g++
3.4.4, Comeau C++ 4.3.3 online (www.comeaucomputing.com), and Dinkumware
(www.dinkumware.com/exam)

////////////////////////////////////////////////////////////////////////
  #include <algorithm>
  #include <vector>

  class Foo
  {
    std::vector<int> m_data;
  public:
    Foo() {};
    explicit Foo(const Foo& rhs) : m_data(rhs.m_data) {};
  };

  int main()
  {
    Foo foo1, foo2;
    std::swap(foo1, foo2);
  }
////////////////////////////////////////////////////////////////////////

Is this little program indeed non-conforming?

Howard Hinnant posted on May 26, on comp.lang.c++ [Re: Style: preferring
parentheses to '=' for initialization?]:
>
> template <class T>
> void swap(T& x, T& y)
> {
>     T tmp = x;
>     x = y;
>     y = tmp;
> }
>
> as coded above this requires T to have a *non-explicit* copy
> constructor.  But:
>
> template <class T>
> void swap(T& x, T& y)
> {
>     T tmp(x);
>     x = y;
>     y = tmp;
> }
>
> will work with a T with an explicit copy constructor.  (I'm still trying
> to figure out why anyone would *want* an explicit copy constructor).

Why anyone would want an explicit copy constructor?  To disable
std::swap for their type T, I guess  :-)  Apparently std::swap is
commonly implemented by doing "T tmp = x".  I wonder if that's the way
it's supposed to be, though...


Kind regards,

  Niels Dekker
  www.xs4all.nl/~nd/dekkerware

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: thorsten.ottosen@dezide.com (Thorsten Ottosen)
Date: Wed, 25 Oct 2006 14:32:25 GMT
Raw View
Niels Dekker - no return address wrote:
> A careful programmer might want to disable std::swap for her class,
> e.g., because her class has a throwing assignment. Now it seems that
> disabling std::swap is achieved by declaring the copy constructor of
> this class explicit!

swap() is funny beast and actually presents two interfaces.

The first is called qualified as in

   std::swap(a,b)

and this is not IMO intended to be a nothrow operation. OTOH

   swap(a,b)

looks into other namespaces (via ADL) for a function called swap(), and
this should IMO be a nothrow operation. The latter can eg. be disabled
by calling a private function inside its definition.

-Thorsten

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]