Topic: Is a Swappable class allowed to throw an exception?
Author: unknown@this.is.invalid ("Niels Dekker (no reply address)")
Date: Thu, 14 Sep 2006 21:33:49 GMT Raw View
Howard Hinnant wrote:
> Thanks Niels. I think you make a good point. I've opened LWG issue 594.
Thank you, Howard! Hopefully providing an appropriate specialization of
std::swap will be sufficient to make a class Swappable in C++0x...
Yet another Swappable question, though. Is it allowed for a Swappable
class to throw an exception, while swapping?
For example, my BadCopier class (see below) throws a bad_alloc in its
copy constructor, as well as in its assignment operator, but still it is
both CopyConstructible and Assignable, or not? So is it Swappable?
My BadSwapper class (further below) throws a bad_alloc whenever its swap
function is called. Still... is it Swappable as well? I doubt it, as
it doesn't meet the post-condition for swap(t, u), as described in the
Draft, Table 32, Swappable requirements:
"t has the value originally held by u, and u has the value originally
held by t."
(Draft: www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf)
Here are my "bad" classes:
------------------------------------------------------------------------
class BadCopier
{
int m_data;
public:
explicit BadCopier(int arg = 0): m_data(arg) {}
BadCopier(const BadCopier& rhs): m_data(rhs.m_data)
{
throw std::bad_alloc();
}
BadCopier & operator=(const BadCopier& rhs)
{
m_data = rhs.m_data;
throw std::bad_alloc();
}
};
class BadSwapper
{
int m_data;
public:
explicit BadSwapper(int arg = 0): m_data(arg) {}
friend void swap(BadSwapper& lhs, BadSwapper& rhs)
{
std::swap(lhs.m_data, rhs.m_data);
throw std::bad_alloc();
}
};
------------------------------------------------------------------------
Please let me know if both classes satisfy the Swappable requirements!
Kind regards,
Niels Dekker
---
[ 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: howard.hinnant@gmail.com (Howard Hinnant)
Date: Thu, 14 Sep 2006 22:22:31 GMT Raw View
In article <4509C736.7EC6301C@this.is.invalid>,
unknown@this.is.invalid ("Niels Dekker (no reply address)") wrote:
> Yet another Swappable question, though. Is it allowed for a Swappable
> class to throw an exception, while swapping?
You raise good points. I believe the current WD says that you can throw
while swapping. The current CopyConstructible requirement has similar
wording to the Swappable requirement, and clearly a copy constructor can
throw.
That being said, a personal coding guideline of mine is that none of
swap, move constructor or move assignment should throw. Bad things
happen. But at this point that's more of a coding guideline than a
standards requirement, and should probably stay that way. Caveat: I have
proposed a corner or two that do require a nothrow move constructor,
e.g.:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1858.html
23.2.4.2 - vector capacity
It amazes me how often a throwing swap or move actually turns out ok
(for a sufficiently lax definition of ok). But on some primeval level,
such things scare me, much like rattle snakes do. Yes, they can be
handled safely. I'm glad other people do that so I don't have to. :-)
-Howard
---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 14 Sep 2006 23:08:15 GMT Raw View
Howard Hinnant wrote:
>
> That being said, a personal coding guideline of mine is that none of
> swap, move constructor or move assignment should throw.
On the other hand, this precludes a small-object optimization for
std::tr1::function. If its swap member function is allowed to throw
exceptions then it can hold small function objects internally rather
than putting them on the free store.
--
-- Pete
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
---
[ 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: howard.hinnant@gmail.com (Howard Hinnant)
Date: Fri, 15 Sep 2006 04:21:38 GMT Raw View
In article <hdWdnTOHHPquQpTYnZ2dnUVZ_omdnZ2d@giganews.com>,
petebecker@acm.org (Pete Becker) wrote:
> > That being said, a personal coding guideline of mine is that none of
> > swap, move constructor or move assignment should throw.
>
> On the other hand, this precludes a small-object optimization for
> std::tr1::function. If its swap member function is allowed to throw
> exceptions then it can hold small function objects internally rather
> than putting them on the free store.
<nod> std::tr1::function is a subject I've been worrying a lot about
lately for a variety of reasons.
In the sso optimizations I've done to date for std::function I restrict
the sso to function pointers and empty function objects. Admittedly
that doesn't restrict empty function objects from throwing on swap, but
it does make it "6-nines" unlikely. And it also allows the sso
optimization for a vast majority of use cases.
But this is a very interesting standards question: How much of this
should be QOI, and how much should be standard?
Fwiw the other area that std::function concerns me is: Does
std::function(F) require F to be CopyConstructible?
I believe it does today. And I'm not happy with that answer. I haven't
come up with a good way to say no to requiring CopyConstructible of F
yet. Perhaps concepts will lend a hand...
-Howard
---
[ 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: petebecker@acm.org (Pete Becker)
Date: Fri, 15 Sep 2006 17:52:36 GMT Raw View
Howard Hinnant wrote:
>
> In the sso optimizations I've done to date for std::function I restrict
> the sso to function pointers and empty function objects. Admittedly
> that doesn't restrict empty function objects from throwing on swap, but
> it does make it "6-nines" unlikely. And it also allows the sso
> optimization for a vast majority of use cases.
>
Doug Gregor mentioned to me a few months ago that he was re-implementing
function, and decided to ignore the possibility that copying a callable
object (note switch to TR1 terminology <g>) might throw an exception. In
my opinion that's exactly right: you don't impose constraints for fringe
cases at the expense of making the mainline harder, bigger, or slower. I
wouldn't call this 6-nines, because that implies statistical data that
almost certainly doesn't exist. Besides, that's too extreme. The best
rule is that almost everything works as advertised, and the cases that
don't are easy to recognize. The more sophisticated the implementation
gets, the harder it is to describe the cases it can't handle.
My analogy is the old through-the-lens metering systems on cameras. They
looked at the overall brightness of the image, and set the exposure to
get a mid-tone. That got 90% of most people's pictures right. If the
subject was backlit (background brighter than subject) that would
produce a picture that was underexposed, and you had to override the
automatic setting to give more exposure. If the background was dark, the
picture would be overexposed, and you had to override the other way.
Then they (Nikon, I think) came out with fancier exposure systems that
looked at five different areas of the image, to get better exposures in
some cases. They got 95% right, but you could no longer just look at the
scene to figure out what whether the exposure would be right or whether
you had to override the automatic setting. Of course, today you get
instant feedback, so you can adjust after you take the first shot. But
that's hacking.
--
-- Pete
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
---
[ 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 reply address)")
Date: Sun, 17 Sep 2006 01:22:00 GMT Raw View
Pete Becker wrote:
> On the other hand, this precludes a small-object optimization for
> std::tr1::function. If its swap member function is allowed to throw
> exceptions then it can hold small function objects internally rather
> than putting them on the free store.
I'm sorry I'm not yet familiar with either std::tr1::function, or
small-object optimization. Can you please explain in more detail why
std::tr1::function or any class with small-object optimization would
need to have a throwing swap?
Kind regards,
Niels Dekker
---
[ 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 ]