By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,317 Members | 2,357 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,317 IT Pros & Developers. It's quick & easy.

conversion: errno => exception

P: n/a
Do you know a class library that can convert the error/return codes
that are listed in the standard header file "errno.h" into a
well-known exception hierarchy?
Did anybody derive it from "std:runtime_error"?

Regards,
Markus
Jul 22 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
* Markus Elfring:
Do you know a class library that can convert the error/return codes
that are listed in the standard header file "errno.h" into a
well-known exception hierarchy?
Did anybody derive it from "std:runtime_error"?


Why do you want a hierarchy?

Off the cuff:

void throwStdIoError()
{
throw std::runtime_error( std::strerror( std::errno ) );
}
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #2

P: n/a
Alf P. Steinbach wrote:
* Markus Elfring:
Do you know a class library that can convert the error/return codes
that are listed in the standard header file "errno.h" into a
well-known exception hierarchy?
Did anybody derive it from "std:runtime_error"?


Why do you want a hierarchy?

Off the cuff:

void throwStdIoError()
{
throw std::runtime_error( std::strerror( std::errno ) );
}


It would be quite hard for the function that catches the exception to find
out what the error actually is.

Jul 22 '05 #3

P: n/a
* Rolf Magnus:
Alf P. Steinbach wrote:
* Markus Elfring:
Do you know a class library that can convert the error/return codes
that are listed in the standard header file "errno.h" into a
well-known exception hierarchy?
Did anybody derive it from "std:runtime_error"?


Why do you want a hierarchy?

Off the cuff:

void throwStdIoError()
{
throw std::runtime_error( std::strerror( std::errno ) );
}


It would be quite hard for the function that catches the exception to find
out what the error actually is.


If it's not within the context of the throwing call, why should it care?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #4

P: n/a
> Why do you want a hierarchy?

The reasons are similar to the design decisions for the base classes
that are specified in the header <exception> and related files.
I would like to unify error reporting and put return codes into groups
or categories. I see a problem there to find the appropriate names for
the categorization.

The application of design patterns is another use case.
- http://www.refactoring.com/catalog/r...ymorphism.html
- http://www.refactoring.com/catalog/r...WithClass.html
- http://industriallogic.com/xp/refact...WithClass.html

I imagine a factory class that provides a method like this one.
errno_exception& create(int err_no) const throw(std::out_of_range);

I suggest two approaches for its implementation.
1. a huge switch statement
2. Instances are copied from a static collection (array, vector or
map).

Have you got more ideas?
Is a complete solution available already?

Regards,
Markus
Jul 22 '05 #5

P: n/a
* Markus Elfring:
Why do you want a hierarchy?
The reasons are similar to the design decisions for the base classes
that are specified in the header <exception> and related files.
I would like to unify error reporting and put return codes into groups
or categories. I see a problem there to find the appropriate names for
the categorization.


If naming is a problem, then the idea is probably not meaningful.

The base classes in <exception> are meant to facilitate different handling
of different kinds of error state, primarily to diffentiate between
recoverable/ignorable on the one hand, and unrecoverable/non-ignorable.

But <exception> is very badly designed (if it is designed at all ;-)).
It probably emerged as a "let's get it over with, choose something!" solution
to a lot of confusion and disagreement. And so for many years Microsoft's
documentation incorrectly referred to a completely different hierarchy...

The application of design patterns is another use case.
- http://www.refactoring.com/catalog/r...ymorphism.html
- http://www.refactoring.com/catalog/r...WithClass.html
- http://industriallogic.com/xp/refact...WithClass.html
Regarding "replaceTypeCodeWithClass", consider how much easier it is to
"replace type code with log message", which is all you ordinarily need.

Do not be blinded by design patterns.

A list of design patterns can be a good source of ideas, but forcing a
pattern on a design is usually UnGood: instead, see what pattern is there
in the first place.

I imagine a factory class that provides a method like this one.
errno_exception& create(int err_no) const throw(std::out_of_range);


Regarding C++ the result should be const, and it's not a good idea to use
std::out_of_range (I haven't checked that the name is correct): instead,
use std::runtime_error or derived classes for recoverable errors, so that
other code won't get an exception it doesn't expect and won't have to
check for a zillion silly different types of exception.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #6

P: n/a
Alf P. Steinbach wrote:
* Rolf Magnus:
Alf P. Steinbach wrote:
> * Markus Elfring:
>> Do you know a class library that can convert the error/return codes
>> that are listed in the standard header file "errno.h" into a
>> well-known exception hierarchy?
>> Did anybody derive it from "std:runtime_error"?
>
> Why do you want a hierarchy?
>
> Off the cuff:
>
> void throwStdIoError()
> {
> throw std::runtime_error( std::strerror( std::errno ) );
> }


It would be quite hard for the function that catches the exception to
find out what the error actually is.


If it's not within the context of the throwing call, why should it care?


If it doesn't care, what's the purpose of the exception?
Jul 22 '05 #7

P: n/a
* Rolf Magnus:
Alf P. Steinbach wrote:
* Rolf Magnus:
Alf P. Steinbach wrote:

> * Markus Elfring:
>> Do you know a class library that can convert the error/return codes
>> that are listed in the standard header file "errno.h" into a
>> well-known exception hierarchy?
>> Did anybody derive it from "std:runtime_error"?
>
> Why do you want a hierarchy?
>
> Off the cuff:
>
> void throwStdIoError()
> {
> throw std::runtime_error( std::strerror( std::errno ) );
> }

It would be quite hard for the function that catches the exception to
find out what the error actually is.


If it's not within the context of the throwing call, why should it care?


If it doesn't care, what's the purpose of the exception?


Most actual code does not use information about the type of a caught
exception.

The only relevant information is, usually, that an exception occurred, and
(for purposes of logging) the explanatory string carried by the exception.

Hence your question is really "why does C++ support exceptions", and that
belongs in [comp.std.c++], or a programming textbook, if anywhere.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #8

P: n/a
On 8 Nov 2004 10:59:11 -0800, Ma************@web.de (Markus Elfring)
wrote:
Why do you want a hierarchy?
The reasons are similar to the design decisions for the base classes
that are specified in the header <exception> and related files.
I would like to unify error reporting and put return codes into groups
or categories. I see a problem there to find the appropriate names for
the categorization.

The application of design patterns is another use case.
- http://www.refactoring.com/catalog/r...ymorphism.html
- http://www.refactoring.com/catalog/r...WithClass.html
- http://industriallogic.com/xp/refact...WithClass.html

I imagine a factory class that provides a method like this one.
errno_exception& create(int err_no) const throw(std::out_of_range);


That isn't going to work, since if you do:

throw create(errno);

the exception object will be sliced, since in C++ the static type of a
throw statement determines the type of exception thrown. This of
course assumes that you are going to add classes derived from
errno_exception.
I suggest two approaches for its implementation.
1. a huge switch statement
2. Instances are copied from a static collection (array, vector or
map).

Have you got more ideas?
You could use a map from error number to a throw function. e.g.

template <class Exception> void thrower(int errorCode/*other
params?*/)
{
throw Exception(errorCode/*other params?*/);
}

and a map:

std::map<int, void(int)> throwers;

Insert in the map with:

throwers[someErrorCode] = &thrower<SomeExceptionClass>;

Then you throw with:

void throwErrNo(int errorNumber/*other params?*/)
{
iterator i = throwers.find(someErrorCode);
if (i != throwers.end())
{
(i->second)(someErrorCode/*other params?*/);
}
else
{
//either throw errno_exception or out_of_range
//or even assert?
}
}

If the sequence of error numbers is fairly contiguous, you could use a
vector rather than a map. Alternatively, you could just use the switch
statement - this depends on whether you want the thing to be runtime
pluggable with new error codes, etc.
Is a complete solution available already?


Not that I know of.

Tom
Jul 22 '05 #9

P: n/a
* Tom Widmer:
* Markus Elfring:

I imagine a factory class that provides a method like this one.
errno_exception& create(int err_no) const throw(std::out_of_range);


That isn't going to work, since if you do:

throw create(errno);

the exception object will be sliced, since in C++ the static type of a
throw statement determines the type of exception thrown. This of
course assumes that you are going to add classes derived from
errno_exception.


Well, what you describe here wasn't mentioned by Markus.

Hence the "that" that isn't going to work is your code... ;-)

Because of that the natural assumption is that his errno_exception is a
factory, or that it directly provides a virtual throw function.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #10

P: n/a
On Tue, 09 Nov 2004 22:29:24 GMT, al***@start.no (Alf P. Steinbach)
wrote:
* Tom Widmer:
* Markus Elfring:
>
>I imagine a factory class that provides a method like this one.
> errno_exception& create(int err_no) const throw(std::out_of_range);


That isn't going to work, since if you do:

throw create(errno);

the exception object will be sliced, since in C++ the static type of a
throw statement determines the type of exception thrown. This of
course assumes that you are going to add classes derived from
errno_exception.


Well, what you describe here wasn't mentioned by Markus.

Hence the "that" that isn't going to work is your code... ;-)

Because of that the natural assumption is that his errno_exception is a
factory, or that it directly provides a virtual throw function.


True, but I thought it was worth highlighting the issue just in case
he wasn't aware of it.

Actually, a virtual throw method is generally a good idea in any
exception heirarchy, along with a clone method, so that you can
propogate exceptions between threads, etc.

Tom
Jul 22 '05 #11

P: n/a
> That isn't going to work, since if you do:

How do you think about an interface like this one?
virtual errno_exception& create(int err_no) const;

throw create(errno);
I would like to use ...
throw my_exception_factory.create(errno);

the exception object will be sliced, since in C++ the static type of a
throw statement determines the type of exception thrown. This of
course assumes that you are going to add classes derived from
errno_exception.


I do not think that "object slicing" will happen.
http://www.savinov.spb.ru/think/tic0161.html#Heading428

How does your statement fit to the handling of "covariant return types"?
http://www.fmi.uni-konstanz.de/~kueh....html#faq-20.6
http://www.fmi.uni-konstanz.de/~kueh....html#faq-22.5
http://semantics.org/once_weakly/ck1...iantreturn.pdf
Jul 22 '05 #12

P: n/a
On 12 Nov 2004 03:14:26 -0800, Ma************@web.de (Markus Elfring)
wrote:
That isn't going to work, since if you do:
How do you think about an interface like this one?
virtual errno_exception& create(int err_no) const;

throw create(errno);


I would like to use ...
throw my_exception_factory.create(errno);


That's exactly what won't work. You will need something like:

my_exception_factory.create(errno).throw_self();

where throw_self is a virtual function that is implemented in every
exception class that simply does throw *this;
Or you can have:

my_exception_factory.throw_error(errno);

or similar.
the exception object will be sliced, since in C++ the static type of a
throw statement determines the type of exception thrown. This of
course assumes that you are going to add classes derived from
errno_exception.


I do not think that "object slicing" will happen.
http://www.savinov.spb.ru/think/tic0161.html#Heading428


Throwing an exception involves copying it. In the statement "throw t"
the static type of t is used to determine the exception that is
thrown. t is copied into a "temporary" exception object of type
static-type-of-t, and this copy will be a slice if the static type of
t doesn't match its dynamic type.
How does your statement fit to the handling of "covariant return types"?
http://www.fmi.uni-konstanz.de/~kueh....html#faq-20.6
http://www.fmi.uni-konstanz.de/~kueh....html#faq-22.5
http://semantics.org/once_weakly/ck1...iantreturn.pdf


I don't think that covariant returns will make any difference here.

Tom
Jul 22 '05 #13

P: n/a
> Throwing an exception involves copying it. In the statement "throw t"
the static type of t is used to determine the exception that is
thrown. t is copied into a "temporary" exception object of type
static-type-of-t, and this copy will be a slice if the static type of
t doesn't match its dynamic type.


How do you think about the effects by the following design sketch?

#include <iostream.h>
#include <errno.h>

struct errno_exception
{
virtual ~errno_exception() {}
virtual int get_code() const { return EZERO; }
};
struct invalid : public errno_exception
{
};
struct invalid_value : public invalid
{
virtual int get_code() const { return EINVAL; }
};
struct invalid_environment : public invalid
{
virtual int get_code() const { return EINVENV; }
};
struct invalid_format : public invalid
{
virtual int get_code() const { return EINVFMT; }
};
struct no_entry : public errno_exception
{
virtual int get_code() const { return ENOENT; }
};
struct exception_factory
{
virtual ~exception_factory() {}
virtual errno_exception& create (int err_no) const = 0;
};
struct factory1 : public exception_factory
{
virtual errno_exception& create (int err_no) const;
};
struct errno_exceptions
{
errno_exception _ZERO;
no_entry _NOENT;
invalid_format _INVFMT;
invalid_environment _INVENV;
invalid_value _INVAL;
};
errno_exceptions my_e_e;
errno_exception& factory1::create (int err_no) const
{
switch (err_no)
{
case ENOENT:
return my_e_e._NOENT;

case EINVFMT:
return my_e_e._INVFMT;

case EINVENV:
return my_e_e._INVENV;

case EINVAL:
return my_e_e._INVAL;

default:
return my_e_e._ZERO;
}
}
struct exception_thrower
{
virtual ~exception_thrower() {}
virtual void create (int code) const = 0;
};
struct factory2 : public exception_thrower
{
virtual void create (int code) const;
};
void factory2::create (int code) const
{
switch (code)
{
case ENOENT:
throw no_entry();

case EINVFMT:
throw invalid_format();

case EINVENV:
throw invalid_environment();

case EINVAL:
throw invalid_value();

default:
throw errno_exception();
}
}
int main ()
{
factory1 f1;

try
{
throw f1.create(EINVFMT);
}
catch (invalid const& i)
{
cout << "1. invalid = " << i.get_code() << endl;
}
catch (errno_exception const& e)
{
cout << "1. errno exception base" << endl;
}

try
{
factory2 f2;
f2.create(EINVFMT);
}
catch (invalid const& i)
{
cout << "2. invalid = " << i.get_code() << endl;
}
catch (errno_exception const& e)
{
cout << "2. errno exception base" << endl;
}

return 0;
}

Jul 22 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.