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

Question about strong exception guarantee

38 views
Skip to first unread message

Daniel

unread,
Jan 23, 2019, 3:32:39 PM1/23/19
to
Consider:

struct A
{
A(int i)
{
if (i % 2)
{
throw std::invalid_argument("Don't like odd!");
}
}
A(const A&) = default;
A(A&&) = default;
A& operator=(const A&) = default;
A& operator=(A&&) = default;
};

struct C
{
std::vector<A> v_;
std::vector<int> w_;

void push_back(int i)
{
if (w_.size() < w_.capacity())
w_.reserve(w_.size() + 1);
v_.push_back(i);
w_.push_back(i % 2);
}
};

int main(int argc, char **argv)
{
C c;
c.push_back(0);
try
{
c.push_back(1);
}
catch (const std::exception&)
{
std::cout << "size: " << c.v_.size() << " " << c.w_.size() << "\n";
}
}

Output:

size of v: 1, w: 1

Would C satisfy the strong exception guarantee? Or have I missed something?

Also, I'd be interested in thoughts about writing tests for exception guarantees.

Thanks,
Daniel

Alf P. Steinbach

unread,
Jan 23, 2019, 3:53:27 PM1/23/19
to
On 23.01.2019 21:32, Daniel wrote:
> if (w_.size() < w_.capacity())
> w_.reserve(w_.size() + 1);

Uhm, that doesn't do anything at all.

Cheers!,

- Alf

Daniel

unread,
Jan 23, 2019, 4:05:27 PM1/23/19
to
On Wednesday, January 23, 2019 at 3:53:27 PM UTC-5, Alf P. Steinbach wrote:
> On 23.01.2019 21:32, Daniel wrote:
> > if (w_.size() < w_.capacity())
> > w_.reserve(w_.size() + 1);
>
> Uhm, that doesn't do anything at all.
>
Indeed. Feel free to make mental substitutions of sense for nonsense, e.g.

if (w_.size()+1 < w_.capacity())
w_.reserve(w_.size() + 1);

Thiago Adams

unread,
Jan 24, 2019, 7:05:40 AM1/24/19
to
Because your sample is big I cannot see where exactly
is the point of your concern.

From C+ standard:

"23.2.1 General container requirements"

"— if an exception is thrown by a push_back() or push_front() function, that function has no effects."

The constructor itself also has strong guarantee.


Appendix E from The C++ programming Language (C++ 03 edition)
is:

"Standard-library Exception Safety"

Paavo Helde

unread,
Jan 24, 2019, 8:05:13 AM1/24/19
to
I guess his question is about whether a change in capacity is "effect"
or not.

Paavo Helde

unread,
Jan 24, 2019, 8:22:28 AM1/24/19
to
This might be bad performance-wise as it will likely cause buffer
reallocation at each push_back(). I would suggest something like:

w_.reserve(w_.size() + std::max(size_t(1), w_.size()/2));


Daniel

unread,
Jan 24, 2019, 8:24:24 AM1/24/19
to
On Thursday, January 24, 2019 at 7:05:40 AM UTC-5, Thiago Adams wrote:
> On Wednesday, January 23, 2019 at 6:32:39 PM UTC-2, Daniel wrote:
> > Consider:
> >
> > struct A
> > {
> > A(int i)
> > {
> > if (i % 2)
> > {
> > throw std::invalid_argument("Don't like odd!");
> > }
> > }
> > A(const A&) = default;
> > A(A&&) = default;
> > A& operator=(const A&) = default;
> > A& operator=(A&&) = default;
> > };
> >
> > struct C
> > {
> > std::vector<A> v_;
> > std::vector<int> w_;
> >
> > void push_back(int i)
> > {
> > if (w_.size()+1 < w_.capacity())
Yes, I know. The question isn't about std::vector, but about C, which
contains two std:vectors. Strong exception guarantee for C would mean
if an operation on either vector resulted in an exception, both vectors
would be in their original state. The question is: does C as I've
written it (with Alf's correction of my typo) satisfy the strong
exception guarantee?

Daniel

Daniel

unread,
Jan 24, 2019, 9:12:34 AM1/24/19
to
Very bad performance wise :-) thanks for the comment.

Öö Tiib

unread,
Jan 24, 2019, 9:59:30 AM1/24/19
to
Strong exception guarantee is about operations (not classes) and it
means that state of objects participating in operation does not
change when exception was thrown during operation.

You likely mean "C::push_back" with "C"? C is relatively unsafe class
it exposes all data members, so anyone can do numerous unsafe
operations with it.

Formally it is not strong. In practice the answer depends on if change
of capacity of vectors in C is change of state of C for your app or not.
Lot of code ignores reserved capacity of vectors and for such it is
not a state.

Daniel

unread,
Jan 24, 2019, 10:19:35 AM1/24/19
to
On Thursday, January 24, 2019 at 9:59:30 AM UTC-5, Öö Tiib wrote:
>
> Strong exception guarantee is about operations (not classes) and it
> means that state of objects participating in operation does not
> change when exception was thrown during operation.
>
> You likely mean "C::push_back" with "C"?

Right

> Formally it is not strong.

> In practice the answer depends on if change
> of capacity of vectors in C is change of state of C for your app or not.
> Lot of code ignores reserved capacity of vectors and for such it is
> not a state.

Okay, that answers my question, thanks. I'll go with the formal answer.

Daniel

0 new messages