Reputation: 1416
I was trying to use a constexpr inside an exception message, but this does not work: The followoing code is compiling well on g++ (using c++11 or c++14).
#include <exception>
constexpr auto TEST = "test";
class test_throw : public std::exception {
public:
virtual const char* what() const throw() {
return (std::string("THROW ")+TEST).c_str();
}
};
int main()
{
throw test_throw{};
}
I wonder why my exception is outputting an empty message, ok that seems like a bad trick, but I don't understand how the message can be empty.
Is there a way to achieve this without replacing the constexpr by a macro ?
Upvotes: 0
Views: 159
Reputation: 69902
Disaster awaits - here's gcc's warning:
<source>: In member function 'virtual const char* test_throw::what() const':
9 : <source>:9:51: warning: function returns address of local variable [-Wreturn-local-addr]
return (std::string("THROW ")+TEST).c_str();
Here are a few ways to make it safe:
Option 1 - derive from a more concrete standard exception, initialising the message in the constructor.
#include <stdexcept>
#include <string>
constexpr auto TEST = "test";
class test_throw : public std::runtime_error
{
public:
test_throw()
: runtime_error(std::string("THROW ")+TEST)
{}
};
Option 2 - construct the message in a thread_safe static way:
class test_throw : public std::exception
{
public:
const char* what() const noexcept
{
thread_local static std::string message;
try
{
message = std::string("THROW ") + TEST;
return message.c_str();
}
catch(...)
{
return "can't give you a message";
}
}
};
Option 3 - reinvent the wheel.
class test_throw : public std::exception
{
std::string message_;
public:
test_throw()
: message_ { std::string("THROW ") + TEST }
{}
const char* what() const noexcept
{
return message_.c_str();
}
};
Upvotes: 5