Topic: swapping std::pairs?


Author: jon@floorboard.com (Jon Biggar)
Date: Mon, 20 Sep 2004 05:22:37 GMT
Raw View
chris wrote:
>> One thing that complicates the issue is exception safety.  If the
>> second swap() operation throws in your template function, it leaves
>> things in an inconsistent state, with neither p1 nor p2 containing a
>> consistent pair.
>>
>> The generic std::swap does not have this problem.
>>
>
> While this swap would have this problem, normal swap can still have the
> problem that when you try to swap a and b you end up with both being
> assigned the value of b, which is surely no better?

Sure it's better.  At least the first and second in both copies of b are
consistent with each other.  With the proposed template specialized
version, you get a's first with b's second and vice versa.

--
Jon Biggar
Floorboard Software
jon@floorboard.com
jon@biggar.org

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dsp@bdal.de (=?ISO-8859-1?Q?=22Daniel_Kr=FCgler_=28ne_Spangenberg=29=22?=)
Date: Mon, 20 Sep 2004 10:44:46 GMT
Raw View
Hello David Held,

David B. Held schrieb:

> Jonathan Biggar wrote:
>
>> [...]
>> One thing that complicates the issue is exception safety.  If the
>> second swap() operation throws in your template function, it leaves
>> things in an inconsistent state, with neither p1 nor p2 containing a
>> consistent pair.
>>
>> The generic std::swap does not have this problem.
>
>
> Swap should probably not throw in the first place, and I can't think
> of a sane implementation that does.


That is not true. It is not so unusual, that a copy constructor or copy
assignment
operator might throw under special circumstances. This usually happens,
if the
corresponding class uses some (limited) resources,  and where the
"allocation"
for such a resource fails. Since the generic swap is implemented in
terms of these
members, it might throw. In most cases such a throwing swap can be prevented
by providing a user-defined spezialized swap for the given class, but I
don't think
that we can enforce that requirement for any user-defined class ("If you
don't provide
such a non-throwing swap for your class, you will have undefined
behaviour").

Greetings from Bremen,

Daniel

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pdimov@gmail.com (Peter Dimov)
Date: Mon, 20 Sep 2004 13:07:32 GMT
Raw View
jon@floorboard.com (Jon Biggar) wrote in message news:<BR%2d.21110$By7.18254@newssvr27.news.prodigy.com>...
> chris wrote:
> >> One thing that complicates the issue is exception safety.  If the
> >> second swap() operation throws in your template function, it leaves
> >> things in an inconsistent state, with neither p1 nor p2 containing a
> >> consistent pair.
> >>
> >> The generic std::swap does not have this problem.
> >>
> >
> > While this swap would have this problem, normal swap can still have the
> > problem that when you try to swap a and b you end up with both being
> > assigned the value of b, which is surely no better?
>
> Sure it's better.  At least the first and second in both copies of b are
> consistent with each other.

void swap( pair<T1, T2> & p1, pair<T1, T2> & p2 )
{
  pair<T1, T2> tmp( p1 ); // OK
  p1 = p2; // p1.second = p2.second throws
  p2 = tmp;
}

Now you have p1.first == p2.first, and the state of p1.second is
unspecified (basic) or unchanged (strong). No?

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Alberto Barbati <AlbertoBarbati@libero.it>
Date: Mon, 20 Sep 2004 23:22:34 CST
Raw View
Jon Biggar wrote:
> chris wrote:
>
>>> One thing that complicates the issue is exception safety.  If the
>>> second swap() operation throws in your template function, it leaves
>>> things in an inconsistent state, with neither p1 nor p2 containing a
>>> consistent pair.
>>>
>>> The generic std::swap does not have this problem.
>>>
>>
>> While this swap would have this problem, normal swap can still have
>> the problem that when you try to swap a and b you end up with both
>> being assigned the value of b, which is surely no better?
>
>
> Sure it's better.  At least the first and second in both copies of b are
> consistent with each other.  <snip>
>

That's not entirely correct. "Normal" swap can indeed break one of two
copies (but not both). See my other post for details.

Alberto

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dsp@bdal.de (=?ISO-8859-1?Q?=22Daniel_Kr=FCgler_=28ne_Spangenberg=29=22?=)
Date: Thu, 16 Sep 2004 15:11:27 GMT
Raw View
Hello Azumanga,

Azumanga schrieb:

> Why doesn't std::pair have an overload of swap, which swaps both of=20
> it's elements? This would seem to be a natural thing to do, and allow=20
> for a more efficent implementation of swap when the elements of the=20
> pair can themselves be more efficently swapped.
>
> In a similar note, the new "tuple" class in tr1 has a similar problem.
>
> I can't see how this could lead to inefficency or a problem, but I=20
> assume it must be possible?


Both std::pair and tr1::tuple are heterogenous containers which store=20
their elements
by value (and **not** via a handle/pointer). How do you propose swapping=20
two instances of
arbitrary types?

If you solve the problem to implement a generally valid heterogenous swap

template <typename T1, typename T2>
void swap(T1& a, T2& b);

you also have solved the missing swap problems of pair and tuple ;-)

Furtheron, lets assume, you provide such a solution, e.g. using=20
boost::lexical_cast or
similar stuff: What is the general advantage of such a function? To my=20
opinion we will
end with something like

template <typename Policy, typename T1, typename T2>
void swap(T1& a, T2& b);

of at least one policy to decide, in which way the transaction shall=20
take place (what is the
intermediate storage?).

Now considering the fact that a class-defined swap member function is=20
usually of special
interest, if at least some of the class internals are of handle-like=20
nature, I don't see this
advantage in case of value-based heterogenous containers like pair and=20
tuple.

Greetings from Bremen,

Daniel Kr=FCgler


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jgottman@carolina.rr.com ("Joe Gottman")
Date: Thu, 16 Sep 2004 21:13:38 GMT
Raw View
"""Daniel Kr   gler (ne Spangenberg)""" <dsp@bdal.de> wrote in message
news:4147EBC2.5000208@bdal.de...

>Both std::pair and tr1::tuple are heterogenous containers which store their
>elements
>by value (and **not** via a handle/pointer). How do you propose swapping
>two instances of
>arbitrary types?

Delegate to the types themselves.

template <class X, class Y>
void swap(std::pair<X,Y> &p1, std::pair<X, Y> &p2)
{
    swap(p1.first, p2.first);
    swap(p1.second, p2.second);
}

If either X or Y has a specialized swap() function defined, this should call
that function.


Joe Gottman


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: chris@bubblescope.net (chris)
Date: Fri, 17 Sep 2004 06:15:17 GMT
Raw View
Daniel Kr=FCgler (ne Spangenberg) wrote:

> Hello Azumanga,
>=20
> Azumanga schrieb:
>=20
>> Why doesn't std::pair have an overload of swap, which swaps both of=20
>> it's elements? This would seem to be a natural thing to do, and allow=20
>> for a more efficent implementation of swap when the elements of the=20
>> pair can themselves be more efficently swapped.
>>
>> In a similar note, the new "tuple" class in tr1 has a similar problem.
>>
>> I can't see how this could lead to inefficency or a problem, but I=20
>> assume it must be possible?
>=20
>=20
>=20
> Both std::pair and tr1::tuple are heterogenous containers which store=20
> their elements
> by value (and **not** via a handle/pointer). How do you propose swappin=
g=20
> two instances of
> arbitrary types?
>=20
> If you solve the problem to implement a generally valid heterogenous sw=
ap
>=20
> template <typename T1, typename T2>
> void swap(T1& a, T2& b);
>=20
> you also have solved the missing swap problems of pair and tuple ;-)
>=20
> Furtheron, lets assume, you provide such a solution, e.g. using=20
> boost::lexical_cast or
> similar stuff: What is the general advantage of such a function? To my=20
> opinion we will
> end with something like
>=20
> template <typename Policy, typename T1, typename T2>
> void swap(T1& a, T2& b);
>=20
> of at least one policy to decide, in which way the transaction shall=20
> take place (what is the
> intermediate storage?).
>=20
> Now considering the fact that a class-defined swap member function is=20
> usually of special
> interest, if at least some of the class internals are of handle-like=20
> nature, I don't see this
> advantage in case of value-based heterogenous containers like pair and=20
> tuple.
>=20
I'm not sure if one of us is confused.. it might be me :)

what I am suggesting is introducing into std something much like (sorry=20
if this isn't actually correct code, but I hope it's fairly close!)

template<class T,class U>
void swap(pair<T,U> &a,pair<T,U> &b) {
swap(a.first,b.first);
swap(a.second,b.second);
}

At the moment if I call swap on a pair, it simply falls through to the=20
"basic" swap, which does {pair<T,U> temp=3Da; a=3Db; b=3Dtemp;}. I can't =
see=20
how adding this specialised swap could ever hurt matters, and if one or=20
both of T or U has it's own specialised swap, then this would improve=20
performance...

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Fri, 17 Sep 2004 06:15:34 GMT
Raw View
Daniel Kr=FCgler (ne Spangenberg) wrote:

> Hello Azumanga,
>=20
> Azumanga schrieb:
>=20
>> Why doesn't std::pair have an overload of swap, which swaps both of=20
>> it's elements? This would seem to be a natural thing to do, and allow=20
>> for a more efficent implementation of swap when the elements of the=20
>> pair can themselves be more efficently swapped.
>>
>> In a similar note, the new "tuple" class in tr1 has a similar problem.
>>
>> I can't see how this could lead to inefficency or a problem, but I=20
>> assume it must be possible?
>=20
>=20
> Both std::pair and tr1::tuple are heterogenous containers which store=20
> their elements
> by value (and **not** via a handle/pointer). How do you propose swappin=
g=20
> two instances of
> arbitrary types?
>=20
> If you solve the problem to implement a generally valid heterogenous sw=
ap
>=20
> template <typename T1, typename T2>
> void swap(T1& a, T2& b);
>=20
> you also have solved the missing swap problems of pair and tuple ;-)
>=20

IIUC, the OP did not intend to swap the two members of one pair, but to=20
swap two pairs (of the same type) memberwise. That is:

template <class T1, class T2>
void swap(pair<T1, T2>& p1, pair<T1, T2>& p2)
{
   swap(p1.first, p2.first);
   swap(p1.second, p2.second);
}

Notice that there are no swaps between heterogenous types.

The OP is surprised, as I am, that such an overload of std::swap is not=20
standardized. Without this overload swapping pairs falls back on the=20
generic std::swap that requires copies of both arguments even if one or=20
both have a more efficient way of swapping.

Alberto

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dsp@bdal.de (=?ISO-8859-1?Q?=22Daniel_Kr=FCgler_=28ne_Spangenberg=29=22?=)
Date: Fri, 17 Sep 2004 16:26:01 GMT
Raw View
Hello Joe Gottman,

Joe Gottman schrieb:

>"""Daniel Kr=FCgler (ne Spangenberg)""" <dsp@bdal.de> wrote in message=20
>news:4147EBC2.5000208@bdal.de...
>
> =20
>
>>Both std::pair and tr1::tuple are heterogenous containers which store t=
heir=20
>>elements
>>by value (and **not** via a handle/pointer). How do you propose swappin=
g=20
>>two instances of
>>arbitrary types?
>>   =20
>>
>
>Delegate to the types themselves.
>
>template <class X, class Y>
>void swap(std::pair<X,Y> &p1, std::pair<X, Y> &p2)
>{
>    swap(p1.first, p2.first);
>    swap(p1.second, p2.second);
>}
>
>If either X or Y has a specialized swap() function defined, this should =
call=20
>that function.
> =20
>

OK, I obviously misunderstood the OP's intend, because I interpreted him=20
as wishing a heterogenous
swap between first and second.

Thanks for clarification,

Daniel

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jon@floorboard.com (Jonathan Biggar)
Date: Fri, 17 Sep 2004 18:13:10 GMT
Raw View
Alberto Barbati wrote:
> IIUC, the OP did not intend to swap the two members of one pair, but to
> swap two pairs (of the same type) memberwise. That is:
>
> template <class T1, class T2>
> void swap(pair<T1, T2>& p1, pair<T1, T2>& p2)
> {
>   swap(p1.first, p2.first);
>   swap(p1.second, p2.second);
> }
>
> Notice that there are no swaps between heterogenous types.
>
> The OP is surprised, as I am, that such an overload of std::swap is not
> standardized. Without this overload swapping pairs falls back on the
> generic std::swap that requires copies of both arguments even if one or
> both have a more efficient way of swapping.

One thing that complicates the issue is exception safety.  If the second
swap() operation throws in your template function, it leaves things in
an inconsistent state, with neither p1 nor p2 containing a consistent pair.

The generic std::swap does not have this problem.

--
Jon Biggar
Floorboard Software
jon@floorboard.com
jon@biggar.org

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dheld@codelogicconsulting.com ("David B. Held")
Date: Sat, 18 Sep 2004 00:03:39 GMT
Raw View
Jonathan Biggar wrote:
> [...]
> One thing that complicates the issue is exception safety.  If the second
> swap() operation throws in your template function, it leaves things in
> an inconsistent state, with neither p1 nor p2 containing a consistent pair.
>
> The generic std::swap does not have this problem.

Swap should probably not throw in the first place, and I can't think
of a sane implementation that does.

Dave

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: chris@bubblescope.net (chris)
Date: Sat, 18 Sep 2004 04:56:45 GMT
Raw View
Jonathan Biggar wrote:
> Alberto Barbati wrote:
>
>> IIUC, the OP did not intend to swap the two members of one pair, but
>> to swap two pairs (of the same type) memberwise. That is:
>>
>> template <class T1, class T2>
>> void swap(pair<T1, T2>& p1, pair<T1, T2>& p2)
>> {
>>   swap(p1.first, p2.first);
>>   swap(p1.second, p2.second);
>> }
>>
>> Notice that there are no swaps between heterogenous types.
>>
>> The OP is surprised, as I am, that such an overload of std::swap is
>> not standardized. Without this overload swapping pairs falls back on
>> the generic std::swap that requires copies of both arguments even if
>> one or both have a more efficient way of swapping.
>
>
> One thing that complicates the issue is exception safety.  If the second
> swap() operation throws in your template function, it leaves things in
> an inconsistent state, with neither p1 nor p2 containing a consistent pair.
>
> The generic std::swap does not have this problem.
>

While this swap would have this problem, normal swap can still have the
problem that when you try to swap a and b you end up with both being
assigned the value of b, which is surely no better?

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Sat, 18 Sep 2004 04:56:56 GMT
Raw View
Jonathan Biggar wrote:
> Alberto Barbati wrote:
>
> One thing that complicates the issue is exception safety.  If the second
> swap() operation throws in your template function, it leaves things in
> an inconsistent state, with neither p1 nor p2 containing a consistent pair.
>
Correct.

> The generic std::swap does not have this problem.
>
Incorrect. The generic std::swap still suffer this problem. The generic
swap looks like this:

  template <class T>
  void swap(T& a, T& b)
  {
    T t = a;
    a = b;
    b = t;
  }

and pairs are copied memberwise. So swapping two pairs is performed like
this:

1) t.first = a.first
2) t.second = a.second
3) a.first = b.first
4) a.second = b.second
5) b.first = t.first
6) b.second = t.second

If one of the assignments in steps 4 or 6 throws an exception, you are
left with one of the two pairs in an unconsistent state. Yes, one broken
pair is better than two broken pairs, but it's still no consolation.

A memberwise swap is not less secure than the generic one. In fact, I
expect it to be more secure in the general case, because it is usually
easier to write a non-throwing swap than it is to write a non-throwing
assignment operator.

Alberto

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: azumanga@bubblescope.net (Azumanga)
Date: Tue, 14 Sep 2004 15:19:39 GMT
Raw View
Why doesn't std::pair have an overload of swap, which swaps both of it's
elements? This would seem to be a natural thing to do, and allow for a
more efficent implementation of swap when the elements of the pair can
themselves be more efficently swapped.

In a similar note, the new "tuple" class in tr1 has a similar problem.

I can't see how this could lead to inefficency or a problem, but I
assume it must be possible?

Thank you,

Chris

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]