This is an example of what I often do when I want to add some information to an exception:
std::stringstream errMsg;
errMsg << \"Could not load config
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!
A really nicer way would be creating a class (or classes) for the exceptions.
Something like:
class ConfigurationError : public std::exception {
public:
ConfigurationError();
};
class ConfigurationLoadError : public ConfigurationError {
public:
ConfigurationLoadError(std::string & filename);
};
The reason is that exceptions are much more preferable than just transferring a string. Providing different classes for the errors, you give developers a chance to handle a particular error in a corresponded way (not just display an error message). People catching your exception can be as specific as they need if you use a hierarchy.
a) One may need to know the specific reason
} catch (const ConfigurationLoadError & ex) {
// ...
} catch (const ConfigurationError & ex) {
a) another does not want to know details
} catch (const std::exception & ex) {
You can find some inspiration on this topic in https://books.google.ru/books?id=6tjfmnKhT24C Chapter 9
Also, you can provide a custom message too, but be careful - it is not safe to compose a message with either std::string
or std::stringstream
or any other way which can cause an exception.
Generally, there is no difference whether you allocate memory (work with strings in C++ manner) in the constructor of the exception or just before throwing - std::bad_alloc
exception can be thrown before the one which you really want.
So, a buffer allocated on the stack (like in Maxim's answer) is a safer way.
It is explained very well at http://www.boost.org/community/error_handling.html
So, the nicer way would be a specific type of the exception and be avoiding composing the formatted string (at least when throwing).
Ran into a similar issue, in that creating custom error messages for my custom exceptions make ugly code. This was my solution:
class MyRunTimeException: public std::runtime_error
{
public:
MyRunTimeException(const std::string &filename):std::runtime_error(GetMessage(filename)) {}
private:
static std::string GetMessage(const std::string &filename)
{
// Do your message formatting here.
// The benefit of returning std::string, is that the compiler will make sure the buffer is good for the length of the constructor call
// You can use a local std::ostringstream here, and return os.str()
// Without worrying that the memory is out of scope. It'll get copied
// You also can create multiple GetMessage functions that take all sorts of objects and add multiple constructors for your exception
}
}
This separates the logic for creating the messages. I had originally thought about overriding what(), but then you have to capture your message somewhere. std::runtime_error already has an internal buffer.
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);