The standard exceptions can be constructed from a std::string:
#include <stdexcept>
char const * configfile = "hardcode.cfg";
std::string const anotherfile = get_file();
throw std::runtime_error(std::string("Failed: ") + configfile);
throw std::runtime_error("Error: " + anotherfile);
Note that the base class std::exception can not be constructed thus; you have to use one of the concrete, derived classes.
Here is my solution:
#include <stdexcept>
#include <sstream>
class Formatter
{
public:
    Formatter() {}
    ~Formatter() {}
    template <typename Type>
    Formatter & operator << (const Type & value)
    {
        stream_ << value;
        return *this;
    }
    std::string str() const         { return stream_.str(); }
    operator std::string () const   { return stream_.str(); }
    enum ConvertToString 
    {
        to_str
    };
    std::string operator >> (ConvertToString) { return stream_.str(); }
private:
    std::stringstream stream_;
    Formatter(const Formatter &);
    Formatter & operator = (Formatter &);
};
Example:
throw std::runtime_error(Formatter() << foo << 13 << ", bar" << myData);   // implicitly cast to std::string
throw std::runtime_error(Formatter() << foo << 13 << ", bar" << myData >> Formatter::to_str);    // explicitly cast to std::string
    There are different exceptions such as runtime_error, range_error, overflow_error,  logic_error, etc.. You need to pass the string into its constructor, and you can concatenate whatever you want to your message. That's just a string operation.
std::string errorMessage = std::string("Error: on file ")+fileName;
throw std::runtime_error(errorMessage);
You can also use boost::format like this:
throw std::runtime_error(boost::format("Error processing file %1") % fileName);
    The following class might come quite handy:
struct Error : std::exception
{
    char text[1000];
    Error(char const* fmt, ...) __attribute__((format(printf,2,3))) {
        va_list ap;
        va_start(ap, fmt);
        vsnprintf(text, sizeof text, fmt, ap);
        va_end(ap);
    }
    char const* what() const throw() { return text; }
};
Usage example:
throw Error("Could not load config file '%s'", configfile.c_str());
    Use string literal operator if C++14 (operator ""s) 
using namespace std::string_literals;
throw std::exception("Could not load config file '"s + configfile + "'"s);
or define your own if in C++11. For instance
std::string operator ""_s(const char * str, std::size_t len) {
    return std::string(str, str + len);
}
Your throw statement will then look like this
throw std::exception("Could not load config file '"_s + configfile + "'"_s);
which looks nice and clean.
Maybe this?
throw std::runtime_error(
    (std::ostringstream()
        << "Could not load config file '"
        << configfile
        << "'"
    ).str()
);
It creates a temporary ostringstream, calls the << operators as necessary and then you wrap that in round brackets and call the .str() function on the evaluated result (which is an ostringstream) to pass a temporary std::string to the constructor of runtime_error.
Note: the ostringstream and the string are r-value temporaries and so go out of scope after this line ends. Your exception object's constructor MUST take the input string using either copy or (better) move semantics.
Additional: I don't necessarily consider this approach "best practice", but it does work and can be used at a pinch. One of the biggest issues is that this method requires heap allocations and so the operator << can throw. You probably don't want that happening; however, if your get into that state your probably have way more issues to worry about!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With