Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

std::exception move, copy, swap

24 views
Skip to first unread message

Christopher J. Pisz

unread,
Nov 5, 2016, 4:46:28 AM11/5/16
to
I am reading about the "copy and swap idiom" online, which is new to me.

I desire to derive from std::runtime error in order to make my own
exception that also contains filename, line, and time it was created.

I do not see a move constructor, or a swap for any of the std
exceptions. Are there any?

Do I just not worry about "the rule of 5" here and stick to the "rule of
3" that I do know?

I am not sure how I would swap that what() from within a derived class.

Öö Tiib

unread,
Nov 5, 2016, 7:34:49 AM11/5/16
to
On Saturday, 5 November 2016 10:46:28 UTC+2, Christopher J. Pisz wrote:
> I am reading about the "copy and swap idiom" online, which is new to me.

Whatever it is they write about they often praise it but forget
to mention the important limitations.

> I desire to derive from std::runtime error in order to make my own
> exception that also contains filename, line, and time it was created.

Note that "copy and swap" won't typically make sense on case of
dynamically polymorphic object hierarchy like 'std::exception'.
You will get objects sliced if you swap within such hierarchy using
base classes.

>
> I do not see a move constructor, or a swap for any of the std
> exceptions. Are there any?

No. Also compiler may not make those implicitly.

>
> Do I just not worry about "the rule of 5" here and stick to the "rule of
> 3" that I do know?
>
> I am not sure how I would swap that what() from within a derived class.

I am not sure why the copy constructor of 'std::exception' is not
'protected' and copy assignment '= delete'. Perhaps there was
something about exceptions that I have forgotten. Why you copy
exceptions? I just throw and catch const references to those.

The usual rule about dynamically polymorphic stuff is that we use
it through additional indirection.
When we need to swap or to assign such then we swap or assign owning
pointers or smart pointers and we do not assign nor copy nor swap
the object itself.
When we really need to dynamically create polymorphic copy of actual
objects (rare case) then we add virtual 'clone' function to the
whole hierarchy.

Paavo Helde

unread,
Nov 5, 2016, 9:32:49 AM11/5/16
to
On 5.11.2016 10:46, Christopher J. Pisz wrote:
> I am reading about the "copy and swap idiom" online, which is new to me.
>
> I desire to derive from std::runtime error in order to make my own
> exception that also contains filename, line, and time it was created.
>
> I do not see a move constructor, or a swap for any of the std
> exceptions. Are there any?

Copying exceptions is in general complicated because one typically does
not know the dynamic type of the exception and there is no base class
nor a virtual clone function in the base class.

Fortunately, there is actually no need to copy exceptions as the
exception objects are logically immutable. Instead one can create
smartpointers to the exception object which can be freely copied, sent
over to other thread, etc:

try {
// ...

} catch(...) {
std::exception_ptr p1 = std::current_exception();
std::exception_ptr p2 = p1;
// ...
}

hth
Paavo

j...@cppcon.org

unread,
Nov 5, 2016, 1:38:56 PM11/5/16
to
On Saturday, November 5, 2016 at 4:34:49 AM UTC-7, Öö Tiib wrote:
> On Saturday, 5 November 2016 10:46:28 UTC+2, Christopher J. Pisz wrote:
> > I am reading about the "copy and swap idiom" online, which is new to me.
>
> Whatever it is they write about they often praise it but forget
> to mention the important limitations.
>
> > I desire to derive from std::runtime error in order to make my own
> > exception that also contains filename, line, and time it was created.
>
> Note that "copy and swap" won't typically make sense on case of
> dynamically polymorphic object hierarchy like 'std::exception'.
> You will get objects sliced if you swap within such hierarchy using
> base classes.
>
> >
> > I do not see a move constructor, or a swap for any of the std
> > exceptions. Are there any?
>
> No. Also compiler may not make those implicitly.
>
> >
> > Do I just not worry about "the rule of 5" here and stick to the "rule of
> > 3" that I do know?
> >
> > I am not sure how I would swap that what() from within a derived class.
>
> I am not sure why the copy constructor of 'std::exception' is not
> 'protected' and copy assignment '= delete'. Perhaps there was
> something about exceptions that I have forgotten. Why you copy
> exceptions? I just throw and catch const references to those.

Catching by reference is the correct thing to do, but the standard requires that exceptions be copyable. The expression "throw Foo{};" implies a copy (although compilers are free to elide this copy).

j...@cppcon.org

unread,
Nov 5, 2016, 1:40:42 PM11/5/16
to
On Saturday, November 5, 2016 at 6:32:49 AM UTC-7, Paavo Helde wrote:
> On 5.11.2016 10:46, Christopher J. Pisz wrote:
> > I am reading about the "copy and swap idiom" online, which is new to me.
> >
> > I desire to derive from std::runtime error in order to make my own
> > exception that also contains filename, line, and time it was created.
> >
> > I do not see a move constructor, or a swap for any of the std
> > exceptions. Are there any?
>
> Copying exceptions is in general complicated because one typically does
> not know the dynamic type of the exception and there is no base class
> nor a virtual clone function in the base class.
>
> Fortunately, there is actually no need to copy exceptions as the
> exception objects are logically immutable.

Exception objects are not necessarily immutable. See boost::exception for an important use case involving modifying exceptions.

Alf P. Steinbach

unread,
Nov 5, 2016, 2:11:22 PM11/5/16
to
On 05.11.2016 09:46, Christopher J. Pisz wrote:
> I am reading about the "copy and swap idiom" online, which is new to me.
>
> I desire to derive from std::runtime error in order to make my own
> exception that also contains filename, line, and time it was created.
>
> I do not see a move constructor, or a swap for any of the std
> exceptions. Are there any?

Nope.

A standard library exception class is guaranteed copyable, but not movable.

When you add state to a non-swappable class you can design that state as
an object with its own copy assignment operator, that uses the copy and
swap idiom. Then for the exception object that this state is part of,
just let the compiler create a default copy assignment operator.


> Do I just not worry about "the rule of 5" here and stick to the "rule of
> 3" that I do know?

You don't have to provide move semantics for your extra state, because
it will not be moved.


> I am not sure how I would swap that what() from within a derived class.

Not sure what you mean here, sorry.


Cheers & hth.,

- Alf

Öö Tiib

unread,
Nov 5, 2016, 2:33:55 PM11/5/16
to
That expression is likely eliding copying most derived type Foo
to object of same type. So that seemingly does not illustrate at all
how and what OP is there planning to "copy and swap".
0 new messages