MokaT
MokaT

Reputation: 1416

Use of constexpr in exception message

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

Answers (1)

Richard Hodges
Richard Hodges

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

Related Questions