Exceptions - On how specific/nonspecific to make them

Started by
14 comments, last by Rattrap 18 years, 9 months ago
Quote:Original post by FlowingOoze

If I'm not mistaken, you actually need to use reference, since the exception might be a subtype of CException (or whatever you use).



What I was trying saying that you should pass by reference, but in my last post I was merely pointing out that you don't have to.

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]

Advertisement
#include <exception>#include <iostream>#include <string>#include <typeinfo>namespace exceptional{		class exception : public std::exception	{		private:					friend class hack;					mutable std::string str;					void prepend(const std::string & pre) const { str=pre+str; };				public:			exception(const std::string & what) : str(what) {};					virtual const char * what() const throw() { return str.c_str(); };						virtual ~exception() throw() {};	};		class hack	{		private:			std::string msg;		public:			hack(const char * m) : msg(m) {};						template<class T>			const T & operator || (const T & e)			{				e.prepend(msg);				return e;			}	};};#define STRINGIFY1(line) #line#define STRINGIFY2(line) STRINGIFY1(line)#define THROW throw exceptional::hack( __FILE__ ":" STRINGIFY2(__LINE__) ": " ) || struct MyException : public exceptional::exception{	MyException(const std::string & msg) : exceptional::exception(msg) {};};using namespace std;void foo(){	THROW MyException("Boo");}main(){	try {		foo();	} catch(const exception & e)	{		cout << typeid(e).name() << " " << e.what() << endl;	}}

What do you think of this? Just cooked it up.
Prints on GCC:
11MyException exceptional.cpp:57: Boo

EDIT:
I just realized that it could be made to work on other exception types that have a string constructor, if hack::operator||() just threw T(msg+T::what()).
#include <stdexcept>#include <iostream>#include <string>#include <typeinfo>namespace exceptional{		class hack	{		private:			std::string msg;		public:			hack(const char * m) : msg(m) {};						template<class T>			void operator || (const T & e)			{				throw T(msg+e.what());			}	};};#define STRINGIFY1(line) #line#define STRINGIFY2(line) STRINGIFY1(line)#define THROW exceptional::hack( __FILE__ ":" STRINGIFY2(__LINE__) ": " ) || struct MyException : public std::logic_error{	MyException(const std::string & msg) : std::logic_error(msg) {};};using namespace std;void foo(){	THROW MyException("Boo");}main(){	try {		foo();	} catch(const exception & e)	{		cout << typeid(e).name() << " " << e.what() << endl;	}}

Here's the improved version.
Quote:Original post by FlowingOoze
I personally derive most of my exceptions from std::runtime_error, since it comes with a constructor that takes a string for what() (so i don't have to write it my self. Call me lazy. ;)


Hmm, so it does. My copies of The C++ Programming Language and The C++ Standard Library A Tutorial and Reference don't list std::runtime_error's interface! Why! [flaming]

EDIT: I just realized I forgot to get an answer for this:

Do you think the exception structs for classes like be placed within the class itself or just within the same namespace as the class? As in:

class Sprite{public:	class SpriteException	{		//blah blah	};	//blah blahprivate:	//blah blah};


or

class SpriteException{	//blah blah};class Sprite{public:	//blah blahprivate:	//blah blah};


? I am leaning towards not sticking it within the actual class itself to reduce clutter. I don't really know though.

[Edited by - load_bitmap_file on June 22, 2005 1:41:11 PM]
Naming exceptions only makes sense if you're actually going to catch them.
Ie. if you'll ever write something like catch(Sprite::SpriteException), which is be pretty awkward. If you really need exception classes that are thrown only by specific classes, then it might be worth it.

[Edited by - FlowingOoze on June 23, 2005 12:05:36 AM]
Quote:Original post by FlowingOoze
Naming exceptions only makes sense if you're actually going to catch them.
Ie. if you'll ever write something like catch(Sprite::SpriteException), which is be pretty ackward. If you really need exception classes that are thrown only by specific classes, then it might be worth it.


I agree. It's a little akward. I use a namespace that hold all of my exceptions and a master include file that I can just tack onto what ever is going to be throwing or handling exceptions.

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]

This topic is closed to new replies.

Advertisement