I see this is an old question but I think that the approach of printing the line in the exception macro is fundamentally flawed and I think I have a better alternative. I assume that the macro is used similar to the following code:
try {
/// code
throw;
}
catch (...) { __EXCEPTION(aMessage); }
With this approach the macro prints the location where the exception was catch'ed. But for troubleshooting and debugging the location where it was throw'n is usually more useful.
To get that information, we can attach the __FILE__ and __LINE__ macros to the exception. However, we still can't get completely rid of macros, but we get at least the exact throw location:
#include <iostream>
#include <exception>
#include <string>
#define MY_THROW(msg) throw my_error(__FILE__, __LINE__, msg)
struct my_error : std::exception
{
my_error(const std::string & f, int l, const std::string & m)
: file(f)
, line(l)
, message(m)
{}
std::string file;
int line;
std::string message;
char const * what() const throw() { return message.c_str(); }
};
void my_exceptionhandler()
{
try {
throw; // re-throw the exception and capture the correct type
}
catch (my_error & e)
{
std::cout << "Exception: " << e.what() << " in line: " << e.line << std::endl;
}
}
int main()
{
try {
MY_THROW("error1");
} catch(...) { my_exceptionhandler(); }
}
There is one additional improvement possible if we are willing to use boost::exception: We can get rid of macro definitons at least in our own code. The whole program gets shorter and the locations of code execution and error handling can be nicely separated:
#include <iostream>
#include <boost/exception/all.hpp>
typedef boost::error_info<struct tag_error_msg, std::string> error_message;
struct error : virtual std::exception, virtual boost::exception { };
struct my_error: virtual error { };
void my_exceptionhandler()
{
using boost::get_error_info;
try {
throw;
}
catch(boost::exception & e)
{
char const * const * file = get_error_info<boost::throw_file>(e);
int const * line = get_error_info<boost::throw_line>(e);
char const * const * throw_func = get_error_info<boost::throw_function>(e);
std::cout << diagnostic_information(e, false)
<< " in File: " << *file << "(" << *line << ")"
" in Function: " << *throw_func;
}
}
int main()
{
try {
BOOST_THROW_EXCEPTION(my_error() << error_message("Test error"));
} catch(...) { my_exceptionhandler(); }
}