Exception safe operator[]

Sep 13, 2009 at 7:00am
Hi everyone,

I am designing a generic Array class and am trying to make it strongly exception safe. I am using an array of auto_ptr's so my set() method is as safe as I want it. However, I also have to provide a subscript operator. Is there any mechanism I can use to make sure that if the user calls myArray[2] = someObject and someObject's assignment operator fails after changing some of the data, then the changes won't be visible? I want to leave my array in a consistent state should such an exception occur. Right now, my implementation simply dereferences the auto_ptr and returns the result but that clearly doesn't work. Thank you all in advance.
Sep 13, 2009 at 8:29am
Why don't define own Vector class?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <vector>
#include <stdexcept>
#include <iostream>

template <typename T>
class MyVector : public std::vector<T>
{
public:
    T operator[](size_t index)
    {
        try
        {
            T retVal(::std::vector<T>::at(index));
            return retVal;
        }
        catch(std::out_of_range)
        {
            return T();
        }
    }
};

int main()
{
    MyVector<size_t> array;
    for(size_t i = 0; i < 9; ++i)
    {
        array.push_back(i);
    }
    for(size_t i = 0; i < array.size() + 1; ++i)
    {
        std::cout << array[i] << '\n';
    }
    return 0;
};


It's Straustroup's idea

But how will you know about out of range?
Last edited on Sep 13, 2009 at 8:44am
Sep 13, 2009 at 10:45am
Have you looked at the vector.at method?
Sep 13, 2009 at 5:45pm
Typically, exception safe assignment is implemented through copy-swap, with the assumption
that swap cannot throw.

As an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Foo {
    int x;
    int y;
    string s;
  public:
    // Note: pass by value.  This is the copy.
    Foo& operator=( Foo rhs ) {
        // None of these should throw.**
        swap( x, rhs.x );
        swap( y, rhs.y );
        swap( s, rhs.s );
        return *this;
    }
};


** Note that the STL-provided templated swap method does not make any no-throw
guarantees beyond that of swapping simple POD types. Obviously in the above example,
swapping the strings _could_ throw, since performing this operation in theory requires
memory allocations***. It is up to the implementor of the type to write a no-throw
specialization of swap() if the default one isn't sufficient.

*** Note further that most string implementations use copy-on-write semantics which
have the side effect of preventing the default swap method from throwing when swapping
strings.


Sep 13, 2009 at 6:09pm
@Dennis: I'm not allowed to use pre-defined classes. Besides, your implementation returns a copy of the object stored in the Array. It won't permit assignment through operator[].

@jsmith: I know how to make my own assignments safe. It's the generic type T's assignment that can fail.

Quite honestly, I don't think there is a way to do what I'm trying to accomplish but thanks for all your replies.
Sep 14, 2009 at 12:15pm
You can't then. Your class cannot ensure that someone else's class implements exception safe assignment.
Sep 14, 2009 at 12:26pm
It's not the container's job to deal with that sort of thing. The user of the container is the same one who specified T, so they ought to be able to deal with it. The best you can do is maintain the coherence of your contianer if such an exception is thrown.
Topic archived. No new replies allowed.