3

I'm having trouble understanding the syntax of exceptions. I have a class template map<T> that has to be able to throw an exception. The code bellow is correct and is used to catch the exception.

try
{       
    map<int> m;
    m["everything"] = 42;
}
catch(map<int>::Uninitialized&)
{
    cout << "Uninitialized map element!" << endl;
}

I was attempting to create a class derived from runtime_error and then throw it from my class. But it seems that my logic is flawed.

class Uninitialized : public runtime_error
{
public:
    Uninitialized() : runtime_error("error") {}
};

T operator[] (const char index[]) const
{
    throw Uninitialized();
    return value;
}
  • 2
    What compiler errors do you get? What is your expected result, and what do you actually get? Please clarify your question. – Mr.C64 Feb 25 '14 at 19:27
  • there are more errors than I can count xD I basically what to use the code that catches the exception. I believe that the problem has to do with the way that I'm trowing, and the way that i'm catching. – user3352790 Feb 25 '14 at 19:33
  • 1
    Aside: given that there's already an `std::map`, you might be better off using a different name. – Jerry Coffin Feb 25 '14 at 19:37
  • In what way does it seem your logic is flawed? What was your premise, and what conclusion did you reach? – Rob Kennedy Feb 25 '14 at 19:50
  • The way that the exception is being catched does correspond to the way that is being thrown. It is catched as a unnamed non-const ref? – user3352790 Feb 25 '14 at 20:03

2 Answers2

4

The basic idea of what you're trying to do is certainly possible, so the exact problem you're encountering isn't entirely clear.

Here's a quick demo that does work, and does roughly what you seem to be trying:

#include <stdexcept>
#include <iostream>

template <class T>
class map { 
public:
    class Uninitialized : public std::runtime_error
    {
    public:
        Uninitialized() : runtime_error("error") {}
    };

    T operator[](const char index[]) const
    {
        throw Uninitialized();
        return T();
    }
};

int main(){ 
    map<int> m;
    try {
        auto foo = m["a"];
    }
    catch (map<int>::Uninitialized &m) {
        std::cerr << "Caught exception:" << m.what()<< "\n";
    }
}
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • I believe the problem is related to this. Trying to fix it now. – user3352790 Feb 25 '14 at 19:59
  • Downvoter: care to explain what you see as a problem here? If there's a real problem, I'd like to fix it... – Jerry Coffin Feb 25 '14 at 20:06
  • 15.3/17 would seem to contradict your assertion that a non-const reference can't be bound to a temporary. Regardless of whether the exception in the `throw` expression is a temporary, it's used to initialize the *exception object*, which is definitely a temporary (15.1/3). Furthermore, the user's first comment on the question indicates that the problem was a compiler error introduced by adding a `runtime_error` base class to the exception. I don't think the method of throwing or catching changed. Was the code incorrect all along? If not, how did the changed ancestry affect it? – Rob Kennedy Feb 25 '14 at 21:45
  • I believe Rob is correct. (See e.g. [here](http://stackoverflow.com/a/18402039/321013).) I think you *can* catch exception by non-const reference, otherwise Boost.Exception wouldn't make much sense. – Martin Ba Feb 25 '14 at 21:55
  • @RobKennedy: Yup--corrected, at least on that point (can't delete, since it's been accepted). – Jerry Coffin Feb 25 '14 at 22:04
0

Let's say you are creating a map type (although the standard library already provides one). You provide operator[], and want it to throw an exception every time someone attempts to access a non-existing key.

Create your exception class:

class unititialized_access : public std::runtime_error
{
    // typical stuff
};

Then, within map<Key, Value>::operator[]:

if (<key doesn't exist>)
    throw unititialized_error("blah blah");

You catch the exception with:

try
{
    m["foo"] = 42;
}
catch (const unitialized_error& e)
{
    // do something
}