Advice on using templates and vector to improve exception handling

J

jdm

Hi,

I've been trying to improve on my program's exception handling, due to
the amount of code duplication resulting from the following (not to
mention the need to recode when the relevant data required five
variables):

struct three_long_int_misc_exception
{
std::string ident_string;
long int err_number1, err_number2, err_number3;
three_long_int_misc_exception(std::string i="Unknown exception
(three_long_int_misc_exception).", long int x=0, long int y=0, long
int z=0)
{
ident_string = i;
err_number1 = x;
err_number2 = y;
err_number3 = z;
}
};

struct three_unsigned_long_int_misc_exception
{
std::string ident_string;
unsigned long int err_number1, err_number2, err_number3;
three_unsigned_long_int_misc_exception(std::string i="Unknown
exception (three_unsigned_long_int_misc_exception).", unsigned long
int x=0, unsigned long int y=0, unsigned long int z=0)
{
ident_string = i;
err_number1 = x;
err_number2 = y;
err_number3 = z;
}
};

struct four_long_int_misc_exception
{
std::string ident_string;
long int err_number1, err_number2, err_number3, err_number4;
four_long_int_misc_exception(std::string i="Unknown exception
(four_long_int_misc_exception).", long int w=0, long int x=0, long int
y=0, long int z=0)
{
ident_string = i;
err_number1 = w;
err_number2 = x;
err_number3 = y;
err_number4 = z;
}
};

(There were also structs for when the exception data consisted only of
one or two ints.)

Although the following was a bit more complicated to throw, it seemed
a better idea:

template <typename T> struct multiple_integer_misc_exception
{
std::string ident_string;
std::vector<T> error_numbers;

multiple_integer_misc_exception()
{
ident_string = "";
error_numbers = std::vector<T>(1);
error_numbers[0] = 0;
}

multiple_integer_misc_exception(std::vector<T>& v, std::string
s="Unknown exception (multiple_integer_misc_exception).")
{
ident_string = s;
error_numbers = std::vector<T>(v.size());
for (int i=0; i < v.size(); i++)
{
error_numbers = v;
}
}
};

However, this doesn't seem to eliminate much of the code duplication
involved in catching the exceptions, as the main() function now needs
to include:

catch (multiple_integer_misc_exception<long int> lmime) //Is there a
better way than these two almost identical catches?
{
std::cout<<'\n'<<lmime.ident_string<<'\t';
for (int i=0; i<lmime.error_numbers.size(); i++)
{
std::cout<<lmime.error_numbers<<' ';
}
std::cout<<std::endl;
return 1;
}
catch (multiple_integer_misc_exception<unsigned long int> ulmime)
{
std::cout<<'\n'<<ulmime.ident_string<<'\t';
for (int i=0; i<ulmime.error_numbers.size(); i++)
{
std::cout<<ulmime.error_numbers<<' ';
}
std::cout<<std::endl;
return 1;
}

Can anyone suggest a better way to do this?

Thanks,

James McLaughlin.
 
G

**Group User**

Hi,

I've been trying to improve on my program's exception handling, due to
the amount of code duplication resulting from the following (not to
mention the need to recode when the relevant data required five
variables):

struct three_long_int_misc_exception
{
        std::string ident_string;
        long int err_number1, err_number2, err_number3;
        three_long_int_misc_exception(std::string i="Unknown exception
(three_long_int_misc_exception).", long int x=0, long int y=0, long
int z=0)
        {
                ident_string = i;
                err_number1 = x;
                err_number2 = y;
                err_number3 = z;
        }

};

struct three_unsigned_long_int_misc_exception
{
        std::string ident_string;
        unsigned long int err_number1, err_number2, err_number3;
        three_unsigned_long_int_misc_exception(std::string i="Unknown
exception (three_unsigned_long_int_misc_exception).", unsigned long
int x=0, unsigned long int y=0, unsigned long int z=0)
        {
                ident_string = i;
                err_number1 = x;
                err_number2 = y;
                err_number3 = z;
        }

};

struct four_long_int_misc_exception
{
        std::string ident_string;
        long int err_number1, err_number2, err_number3, err_number4;
        four_long_int_misc_exception(std::string i="Unknown exception
(four_long_int_misc_exception).", long int w=0, long int x=0, long int
y=0, long int z=0)
        {
                ident_string = i;
                err_number1 = w;
                err_number2 = x;
                err_number3 = y;
                err_number4 = z;
        }

};

(There were also structs for when the exception data consisted only of
one or two ints.)

Although the following was a bit more complicated to throw, it seemed
a better idea:

template <typename T> struct multiple_integer_misc_exception
{
        std::string ident_string;
        std::vector<T> error_numbers;

        multiple_integer_misc_exception()
        {
                ident_string = "";
                error_numbers = std::vector<T>(1);
                error_numbers[0] = 0;
        }

        multiple_integer_misc_exception(std::vector<T>& v, std::string
s="Unknown exception (multiple_integer_misc_exception).")
        {
                ident_string = s;
                error_numbers = std::vector<T>(v.size());
                for (int i=0; i < v.size(); i++)
                {
                        error_numbers = v;
                }
        }

};

However, this doesn't seem to eliminate much of the code duplication
involved in catching the exceptions, as the main() function now needs
to include:

        catch (multiple_integer_misc_exception<long int> lmime)   //Is there a
better way than these two almost identical catches?
        {
                std::cout<<'\n'<<lmime.ident_string<<'\t';
                for (int i=0; i<lmime.error_numbers.size(); i++)
                {
                        std::cout<<lmime.error_numbers<<' ';
                }
                std::cout<<std::endl;
                return 1;
        }
        catch (multiple_integer_misc_exception<unsigned long int> ulmime)
        {
                std::cout<<'\n'<<ulmime.ident_string<<'\t';
                for (int i=0; i<ulmime.error_numbers.size(); i++)
                {
                        std::cout<<ulmime.error_numbers<<' ';
                }
                std::cout<<std::endl;
                return 1;
        }

Can anyone suggest a better way to do this?

Thanks,

James McLaughlin.


Dear Sir, this googlegroups is hosted by Google's Finance Manager
DavidC - a known colored gay male living at present in Vietnam Sir
HIs Vietnamese name mmm if I am wrong is Trung Kien, if you are
accessing from a Vietnamese forums board definitely you will see suc
username, it's the 'man'
 
S

sebastian

Hi,

I've been trying to improve on my program's exception handling, due to
the amount of code duplication resulting from the following (not to
mention the need to recode when the relevant data required five
variables):

struct three_long_int_misc_exception
{
        std::string ident_string;
        long int err_number1, err_number2, err_number3;
        three_long_int_misc_exception(std::string i="Unknown exception
(three_long_int_misc_exception).", long int x=0, long int y=0, long
int z=0)
        {
                ident_string = i;
                err_number1 = x;
                err_number2 = y;
                err_number3 = z;
        }

};

struct three_unsigned_long_int_misc_exception
{
        std::string ident_string;
        unsigned long int err_number1, err_number2, err_number3;
        three_unsigned_long_int_misc_exception(std::string i="Unknown
exception (three_unsigned_long_int_misc_exception).", unsigned long
int x=0, unsigned long int y=0, unsigned long int z=0)
        {
                ident_string = i;
                err_number1 = x;
                err_number2 = y;
                err_number3 = z;
        }

};

struct four_long_int_misc_exception
{
        std::string ident_string;
        long int err_number1, err_number2, err_number3, err_number4;
        four_long_int_misc_exception(std::string i="Unknown exception
(four_long_int_misc_exception).", long int w=0, long int x=0, long int
y=0, long int z=0)
        {
                ident_string = i;
                err_number1 = w;
                err_number2 = x;
                err_number3 = y;
                err_number4 = z;
        }

};

(There were also structs for when the exception data consisted only of
one or two ints.)

Although the following was a bit more complicated to throw, it seemed
a better idea:

template <typename T> struct multiple_integer_misc_exception
{
        std::string ident_string;
        std::vector<T> error_numbers;

        multiple_integer_misc_exception()
        {
                ident_string = "";
                error_numbers = std::vector<T>(1);
                error_numbers[0] = 0;
        }

        multiple_integer_misc_exception(std::vector<T>& v, std::string
s="Unknown exception (multiple_integer_misc_exception).")
        {
                ident_string = s;
                error_numbers = std::vector<T>(v.size());
                for (int i=0; i < v.size(); i++)
                {
                        error_numbers = v;
                }
        }

};

However, this doesn't seem to eliminate much of the code duplication
involved in catching the exceptions, as the main() function now needs
to include:

        catch (multiple_integer_misc_exception<long int> lmime)   //Is there a
better way than these two almost identical catches?
        {
                std::cout<<'\n'<<lmime.ident_string<<'\t';
                for (int i=0; i<lmime.error_numbers.size(); i++)
                {
                        std::cout<<lmime.error_numbers<<' ';
                }
                std::cout<<std::endl;
                return 1;
        }
        catch (multiple_integer_misc_exception<unsigned long int> ulmime)
        {
                std::cout<<'\n'<<ulmime.ident_string<<'\t';
                for (int i=0; i<ulmime.error_numbers.size(); i++)
                {
                        std::cout<<ulmime.error_numbers<<' ';
                }
                std::cout<<std::endl;
                return 1;
        }

Can anyone suggest a better way to do this?

Thanks,

James McLaughlin.


Hint: encapsulate everything in the "catch" block into a template
function.
 
Ö

Öö Tiib

Hi,

I've been trying to improve on my program's exception handling, due to
the amount of code duplication resulting from the following (not to
mention the need to recode when the relevant data required five
variables):

struct three_long_int_misc_exception
{
        std::string ident_string;
        long int err_number1, err_number2, err_number3;
        three_long_int_misc_exception(std::string i="Unknown exception
(three_long_int_misc_exception).", long int x=0, long int y=0, long
int z=0)
        {
                ident_string = i;
                err_number1 = x;
                err_number2 = y;
                err_number3 = z;
        }

};

struct three_unsigned_long_int_misc_exception
{
        std::string ident_string;
        unsigned long int err_number1, err_number2, err_number3;
        three_unsigned_long_int_misc_exception(std::string i="Unknown
exception (three_unsigned_long_int_misc_exception).", unsigned long
int x=0, unsigned long int y=0, unsigned long int z=0)
        {
                ident_string = i;
                err_number1 = x;
                err_number2 = y;
                err_number3 = z;
        }

};

struct four_long_int_misc_exception
{
        std::string ident_string;
        long int err_number1, err_number2, err_number3, err_number4;
        four_long_int_misc_exception(std::string i="Unknown exception
(four_long_int_misc_exception).", long int w=0, long int x=0, long int
y=0, long int z=0)
        {
                ident_string = i;
                err_number1 = w;
                err_number2 = x;
                err_number3 = y;
                err_number4 = z;
        }

};

(There were also structs for when the exception data consisted only of
one or two ints.)

Although the following was a bit more complicated to throw, it seemed
a better idea:

template <typename T> struct multiple_integer_misc_exception
{
        std::string ident_string;
        std::vector<T> error_numbers;

        multiple_integer_misc_exception()
        {
                ident_string = "";
                error_numbers = std::vector<T>(1);
                error_numbers[0] = 0;
        }

        multiple_integer_misc_exception(std::vector<T>& v, std::string
s="Unknown exception (multiple_integer_misc_exception).")
        {
                ident_string = s;
                error_numbers = std::vector<T>(v.size());
                for (int i=0; i < v.size(); i++)
                {
                        error_numbers = v;
                }
        }

};

However, this doesn't seem to eliminate much of the code duplication
involved in catching the exceptions, as the main() function now needs
to include:

        catch (multiple_integer_misc_exception<long int> lmime)   //Is there a
better way than these two almost identical catches?
        {
                std::cout<<'\n'<<lmime.ident_string<<'\t';
                for (int i=0; i<lmime.error_numbers.size(); i++)
                {
                        std::cout<<lmime.error_numbers<<' ';
                }
                std::cout<<std::endl;
                return 1;
        }
        catch (multiple_integer_misc_exception<unsigned long int> ulmime)
        {
                std::cout<<'\n'<<ulmime.ident_string<<'\t';
                for (int i=0; i<ulmime.error_numbers.size(); i++)
                {
                        std::cout<<ulmime.error_numbers<<' ';
                }
                std::cout<<std::endl;
                return 1;
        }

Can anyone suggest a better way to do this?


Try to have not so lot of exception classes, templates or what not and
lot of complex data within your exceptions. Complex exceptions may
start to contain bugs of their own if you continue like that. The part
that did catch the exception has no much to do anyway. It can either
retry the operation it tried or accept that it failed.

What failed and reasons why it failed are usually displayed or logged
so string describing it is usually all what is needed. If the
explanations contain numeric data then that may be
std::stringstream'ed or boost::format'ed into the string as well.

Simplest is to derive your exceptions from std::exception. Override
the what() of your exceptions. Catch in main() will look like:

catch (std::exception& e)
{
std::cout << "Unrecoverable error: "
<< e.what()
<< std::endl;
return 1;
}

If there are numerous possible errors (like when parsing human-entered
text that must fulfill complex set of rules) then some sort of numeric
error-code may also help (to construct url to manual page about that
error). But this is already above common functionality of exceptions.
 
J

jdm

Hint: encapsulate everything in the "catch" block into a template
function.

Thanks - good point!

But do you know of any way I can reduce the number of catch blocks
needed in the previous example?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top