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

Handling errors within templated classes

P: n/a
I have a Stack class that works fine. In particular, when it
encounters an error, it cout's a msg and exits. However, I'd like to
change it to report the error and continue with dummy data as
necessary. My problem is how to construct dummy data consistent with
the type the class was instantiated with.

My class, stripped to it's essentials for my purpose here, is:

template <class T>
class Stack {
public:
T pop()
{
if ( top < 0 )
{
cout << "Error\n";
return WHAT;
}
return st[top--];
}
private:
int top;
T st[5];
};

How might the "return WHAT;" statement be coded to yield something
like:

if ( typeof(T) == int
doThis(0);
else
doThat("xxx");

It was recommended by one person that I check out "template
specialization", which I Googled. I found several offerings, but I
don't think they were applicable to the situation I'm trying to
address (but maybe I'm wrong).

I'm running MinGW on WinXP-Pro/.SP2.

Thanks in Advance,
Richard

Oct 30 '07 #1
Share this Question
Share on Google+
8 Replies


P: n/a
RichardOnRails wrote:
I have a Stack class that works fine. In particular, when it
encounters an error, it cout's a msg and exits. However, I'd like to
change it to report the error and continue with dummy data as
necessary. My problem is how to construct dummy data consistent with
the type the class was instantiated with.

My class, stripped to it's essentials for my purpose here, is:

template <class T>
class Stack {
public:
T pop()
{
if ( top < 0 )
{
cout << "Error\n";
return WHAT;
You can obtain a default value for T by using the default constructor
(provided T has one):

return ( T() );
}
return st[top--];
}
private:
int top;
T st[5];
};

How might the "return WHAT;" statement be coded to yield something
like:

if ( typeof(T) == int
doThis(0);
else
doThat("xxx");

It was recommended by one person that I check out "template
specialization", which I Googled. I found several offerings, but I
don't think they were applicable to the situation I'm trying to
address (but maybe I'm wrong).
I am not following the doThis() vs. doThat() example. In particular, I have
no idea what the "xxx" is doing there.
BTW: The stack class looks fishy. Poping off an empty stack should trigger
an assert(). If you really want the program to continue, you may opt for
throwing an exception. If you return invented data, client code has no
chance detecting that there way an error.

Also: a hard-coded limit size of 5 is (a) rather small and (b) not
necessary at all. Why don't you use std::stack<>?
Best

Kai-Uwe Bux
Oct 30 '07 #2

P: n/a
On Oct 30, 1:20 am, Kai-Uwe Bux <jkherci...@gmx.netwrote:
RichardOnRails wrote:
I have a Stack class that works fine. In particular, when it
encounters an error, it cout's a msg and exits. However, I'd like to
change it to report the error and continue with dummy data as
necessary. My problem is how to construct dummy data consistent with
the type the class was instantiated with.
My class, stripped to it's essentials for my purpose here, is:
template <class T>
class Stack {
public:
T pop()
{
if ( top < 0 )
{
cout << "Error\n";
return WHAT;

You can obtain a default value for T by using the default constructor
(provided T has one):

return ( T() );
}
return st[top--];
}
private:
int top;
T st[5];
};
How might the "return WHAT;" statement be coded to yield something
like:
if ( typeof(T) == int
doThis(0);
else
doThat("xxx");
It was recommended by one person that I check out "template
specialization", which I Googled. I found several offerings, but I
don't think they were applicable to the situation I'm trying to
address (but maybe I'm wrong).

I am not following the doThis() vs. doThat() example. In particular, I have
no idea what the "xxx" is doing there.

BTW: The stack class looks fishy. Poping off an empty stack should trigger
an assert(). If you really want the program to continue, you may opt for
throwing an exception. If you return invented data, client code has no
chance detecting that there way an error.

Also: a hard-coded limit size of 5 is (a) rather small and (b) not
necessary at all. Why don't you use std::stack<>?

Best

Kai-Uwe Bux
Hi Kai-Uwe,

Thanks for your response.

Your questions/suggestions are well founded. However, I was using a
"toy" application to test alternative error-handling strategies. One
was to trap the error, display a msg and exit the app. However,
sometimes it's desirable to recover somehow from errors so that
additional errors can be exposed in a single pass through all the
calls in an app.

I finally came up with a way to do that. If you're still interested,
tell me what you think of the following example, which compiles with
the current version of MinGW's g++ and executes as intended: it
exposes two errors.

Regards,
Richard
// TemplateErrHandler.c++
// K:\_Projects\C++\MinGW\04a_TemplateErrHandler\

#include <string>
#include <iostream>
using namespace std;

template <class T>
class MyClass {
public:
MyClass() {}
T MyFn()
{
/* Invalid attampts:
return -1029384756; // Error flag
return "My Message"; // Error flag
*/

// Correct attempt:
cout << "ERROR: An error was detected; execution continuing\n";
T tObj;
return tOverloaded(tObj);
}
private:
int n;
int tOverloaded(int val) {return -1029384756;}
char* tOverloaded(string val){return "My Message";}
};

int main ()
{
MyClass<intintInstance;
cout << "From intInstance: " << intInstance.MyFn() << "\n";

MyClass<stringstrInstance;
cout << "From strInstance: " << strInstance.MyFn() << "\n";
}



Oct 30 '07 #3

P: n/a
Hi

RichardOnRails wrote:
I was using a "toy" application to test alternative error-handling
strategies. One was to trap the error, display a msg and exit the app.
However, sometimes it's desirable to recover somehow from errors so that
additional errors can be exposed in a single pass through all the
calls in an app.
Could you explain what kind of errors you want to detect?
I finally came up with a way to do that. If you're still interested,
tell me what you think of the following example, which compiles with
the current version of MinGW's g++ and executes as intended: it
exposes two errors.
Please explain in more detail what exactly you want to do, because I cannot
extract it from the example you give (nor from your previous posting...)
#include <string>
#include <iostream>
using namespace std;

template <class T>
class MyClass {
public:
MyClass() {}
T MyFn()
{
/* Invalid attampts:
return -1029384756; // Error flag
return "My Message"; // Error flag
*/

// Correct attempt:
cout << "ERROR: An error was detected; execution continuing\n";
T tObj;
return tOverloaded(tObj);
Okay... you create a default object tObj of type T. The value you return is
the return value of another overloaded function, named tOverloaded. This
return value does not at all depend on tObj (Question: Why do you create
the object, then?) Furthermore, for types T where no conversion to either
int or std::string exists, the instantiation of MyClass<T>::MyFn will fail.
}
private:
int n;
You _never_ use n. Why do you declare it?
int tOverloaded(int val) {return -1029384756;}
char* tOverloaded(string val){return "My Message";}
Don't use the string-literal-to-char-pointer conversion. It's only there for
C-compatibility (string literals are immutable). I think you wanted to
return string there. Furthermore: Is there _any_ reason why you return "My
Message" and -1029384756?
};

int main ()
{
MyClass<intintInstance;
cout << "From intInstance: " << intInstance.MyFn() << "\n";

MyClass<stringstrInstance;
cout << "From strInstance: " << strInstance.MyFn() << "\n";
}
So you are using MyClass<Tto return some arbitrary T value.

WHY?

And why don't you simply use:

template<typename TT some_value();
template<string some_value<string>() { return "My Message"; }
template<int some_value<int>() { return -1029384756; }

int main()
{
cout << "From int: " << some_value<int>() << "\n";
cout << "From str: " << some_value<string>() << "\n";
}

And what does this have to do with error handling and/or exposing two
errors?

Markus

Oct 30 '07 #4

P: n/a
On Oct 30, 9:42 am, Markus Moll <markus.m...@esat.kuleuven.ac.be>
wrote:
Hi

RichardOnRails wrote:
I was using a "toy" application to test alternative error-handling
strategies. One was to trap the error, display a msg and exit the app.
However, sometimes it's desirable to recover somehow from errors so that
additional errors can be exposed in a single pass through all the
calls in an app.

Could you explain what kind of errors you want to detect?
I finally came up with a way to do that. If you're still interested,
tell me what you think of the following example, which compiles with
the current version of MinGW's g++ and executes as intended: it
exposes two errors.

Please explain in more detail what exactly you want to do, because I cannot
extract it from the example you give (nor from your previous posting...)
#include <string>
#include <iostream>
using namespace std;
template <class T>
class MyClass {
public:
MyClass() {}
T MyFn()
{
/* Invalid attampts:
return -1029384756; // Error flag
return "My Message"; // Error flag
*/
// Correct attempt:
cout << "ERROR: An error was detected; execution continuing\n";
T tObj;
return tOverloaded(tObj);

Okay... you create a default object tObj of type T. The value you return is
the return value of another overloaded function, named tOverloaded. This
return value does not at all depend on tObj (Question: Why do you create
the object, then?) Furthermore, for types T where no conversion to either
int or std::string exists, the instantiation of MyClass<T>::MyFn will fail.
}
private:
int n;

You _never_ use n. Why do you declare it?
int tOverloaded(int val) {return -1029384756;}
char* tOverloaded(string val){return "My Message";}

Don't use the string-literal-to-char-pointer conversion. It's only there for
C-compatibility (string literals are immutable). I think you wanted to
return string there. Furthermore: Is there _any_ reason why you return "My
Message" and -1029384756?
};
int main ()
{
MyClass<intintInstance;
cout << "From intInstance: " << intInstance.MyFn() << "\n";
MyClass<stringstrInstance;
cout << "From strInstance: " << strInstance.MyFn() << "\n";
}

So you are using MyClass<Tto return some arbitrary T value.

WHY?

And why don't you simply use:

template<typename TT some_value();
template<string some_value<string>() { return "My Message"; }
template<int some_value<int>() { return -1029384756; }

int main()
{
cout << "From int: " << some_value<int>() << "\n";
cout << "From str: " << some_value<string>() << "\n";

}

And what does this have to do with error handling and/or exposing two
errors?

Markus
Hi,

Did you read the original post? I think that explains what I was
trying to do.

In Ruby, if I suspected that an object reference I had referred either
to a string or a number, I could write:

if obj.responds_to(zero?) puts "obj refers to a number"
else if obj.responds_to(upcase) puts "obj refers to a string"
else puts "Who knows what obj refers to?"

Stoustrup omitted such a capability from C++. I wanted effect such a
capability, and that's what my example does.

Maybe the following version will be more illustative.
--
Richard
// TemplateErrHandler.c++
// K:\_Projects\C++\MinGW\04a_TemplateErrHandler\

/*TEST RESULTS:
K:\_Projects\C++\MinGW\04a_TemplateErrHandler>g++ TemplateErrHandler.c
++

K:\_Projects\C++\MinGW\04a_TemplateErrHandler>a
ERROR: An error was detected; execution continuing
From intInstance: -1029384756
ERROR: An error was detected; execution continuing
From strInstance: My Message

K:\_Projects\C++\MinGW\04a_TemplateErrHandler>
*/

#include <string>
#include <iostream>
using namespace std;

template <class T>
class MyClass {
public:
MyClass() {}
T MyFn()
{
/* Invalid attampts:
return -1029384756; // Error flag
return "My Message"; // Error flag
*/

// Correct attempt:
cout << "ERROR: An error was detected; \n"
<< " execution will continue \n"
<< " by returning an artifical value.\n";
T tObj;
return tOverloaded(tObj);
}
private:
int n;
int tOverloaded(int val) {return -1029384756;}
char* tOverloaded(string val){return "My Message";}
};

int main ()
{
MyClass<intintInstance;
cout << "Return value from intInstance: " << intInstance.MyFn() << "\n
\n";

MyClass<stringstrInstance;
cout << "Return value from strInstance: " << strInstance.MyFn() << "\n
\n";
}
Oct 30 '07 #5

P: n/a
private:
int n;
You're right: I never used it. I originally thought I needed it, and
then forgot to remove it. I've done so now.
---
R.

Oct 30 '07 #6

P: n/a
RichardOnRails wrote:
On Oct 30, 1:20 am, Kai-Uwe Bux <jkherci...@gmx.netwrote:
RichardOnRails wrote:
Your questions/suggestions are well founded. However, I was
using a "toy" application to test alternative error-handling
strategies. One was to trap the error, display a msg and
exit the app. However, sometimes it's desirable to recover
somehow from errors so that additional errors can be exposed
in a single pass through all the calls in an app.
There are two standard solutions for this problem, depending on
the types of errors you're interested in. If the error is
something "exceptional", i.e. something which won't normally
occur (like disk full or insufficient memory), you should
definitely raise an exception. If the error is something
"normal" (just about any errors in user input, for example), the
usual solution is to use some variant of the Barton and Nackman
"Fallible" idiom, perhaps extended to allow additional
information concerning the error. (There's an implementation
supporting extended error codes at my site:
http://kanze.james.neuf.fr/code-en.html, in the Basic
subsystem.)

Another, less frequently used idiom is to provide a callback.
I finally came up with a way to do that. If you're still
interested, tell me what you think of the following example,
which compiles with the current version of MinGW's g++ and
executes as intended: it exposes two errors.
It has two major flaws: the calling code doesn't know that there
was an error, and it outputs error messages to std::cout, which
is not necessarily where the client code wants them.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Oct 31 '07 #7

P: n/a
"Alf P. Steinbach" <al***@start.nowrote in news:13*************@corp.supernews.com:
>subsystem.)

That's good advice, but the advice about choosing exceptions or not
based on how "exceptional" the situation is IMO ungood advice -- no
matter that it is advice that's (mindlessly, and with reference to some
"authority") repeated by a majority of C++ programmers.

In addition to being so vague and subjective as to be worthless, it's
worthless because what can be "exceptional" in one context need not be
exceptional in some other context.

Instead, use exceptions where they provide clarity and are most
practical -- same advice as for use of loop constructs and other
language constructs.


I like the rule of thumb given on the boost site. Use exceptions if what you want is
stack unwinding, otherwise use an error code. In other words, if you generally expect
the immediate caller to handle the error in some way, don't use exceptions. If you
expect the error to be handled at a higher level than the immediate caller, then an
exception might well be the way to go.

joe
Oct 31 '07 #8

P: n/a
On Oct 31, 11:37 am, Joe Greer <jgr...@doubletake.comwrote:
"Alf P. Steinbach" <al...@start.nowrote innews:13*************@corp.supernews.com:
subsystem.)
That's good advice, but the advice about choosing exceptions or not
based on how "exceptional" the situation is IMO ungood advice -- no
matter that it is advice that's (mindlessly, and with reference to some
"authority") repeated by a majority of C++ programmers.
In addition to being so vague and subjective as to be worthless, it's
worthless because what can be "exceptional" in one context need not be
exceptional in some other context.
Instead, use exceptions where they provide clarity and are most
practical -- same advice as for use of loop constructs and other
language constructs.

I like the rule of thumb given on the boost site. Use exceptions if what you want is
stack unwinding, otherwise use an error code. In other words, if you generally expect
the immediate caller to handle the error in some way, don't use exceptions. If you
expect the error to be handled at a higher level than the immediate caller, then an
exception might well be the way to go.

joe
Hey guys, thanks for your additional ideas. I was just playing around
with a stack implementation I downloaded because I hadn't written any C
++ since I retired 6 years ago. Because it was using it merely as a
toy I added rudimentary error handling with messages directed to
stdout with immediate exit thereafter.

Then I thought I should play with the idea of adding a boolean DEBUG
symbol to allow reporting multiple error in a single session.
However, allowing continued execution after issuing an error message
proved problematical when the offending method's definition specified
a templated return type.

In the latter case, I had to be conjure a suitable dummy return
value. And that value had to be a literal of of the templated type.
I had in mind the ease with which I could that in Ruby, which is rich
in metaprogramming facilities. But nothing came to mind for C++.
Hence the post.

Then the idea of creating overload methods came to me and I was a
happy campler. So I'm signing off from this thread with thanks to all
respondents. I will keep your ideas in mind if I ever do serious C++
programming again.
--
Richard

Nov 1 '07 #9

This discussion thread is closed

Replies have been disabled for this discussion.