I was playing with c++ exceptions and I've tried throwing an anonymous exception like this:
throw class : public std::exception
{
virtual const char *what() const noexcept
{
return "Custom exception";
}
} ex;
However I'm getting the following error when trying to compile:
error: expected primary-expression before ‘class’
throw class : public std::exception
^
My compiler is gcc 5.2.1 on Linux x86_64.
How can I achieve the desired result?
This is not an answer per-se, but some important information what will help you going forward:
First, throwing an anonymous exception is unlikely to be useful. Exceptions are caught by their type. If you can't name the type, you can't catch the exception explicitly - only by its base, in which case you may as well have just thrown the base.
Second (and this is important):
There's rarely a good reason to derive from std::exception directly. You should derive from one of the exception types defined in <stdexcept>
these are:
std::runtime_error - indicating that some runtime condition makes it impossible to perform the service at the moment (such as a missing file).
std::logic_error - indicating that what was attempted will never be possible and the program is fundamentally in error in a way that could not be detected at compile time.
Handy reference here:
http://en.cppreference.com/w/cpp/header/stdexcept
You can't declare a class in a throw statement. Declare the class first (anonymously if you like, naming it via a typedef), then you can throw it.
Better is to name the exception class, but put it in the nameless namespace:
namespace {
class LocalException : public std::exception {
const char *what() const noexcept override {
return "Custom exception";
}
};
}
....
throw LocalException();
or, if you insist, you can create an object of anonymous class, and throw that.
static class : public std::exception {
const char *what() const noexcept override {
return "Custom exception";
}
} LocalExceptionObject;
....
throw LocalExceptionObject;
Edit If you create a typedef, somebody can copy it, and it names the same class. You have to create an object of the anonymous class, and then nobody can name it.
Having said that, I don't think having anonymous things is useful. Far better to declare the class in a nameless namespace (so you know it is private), and just use it.
Related
In a code review recently, I had some less than kind words for something I thought awful. It turns out that it was obviously inspired by the QuantLib::Error class, which looks like this:
//! Base error class
class Error : public std::exception {
public:
/*! The explicit use of this constructor is not advised.
Use the QL_FAIL macro instead.
*/
Error(const std::string& file,
long line,
const std::string& functionName,
const std::string& message = "");
#ifdef QL_PATCH_MSVC_2013
/*! the automatically generated destructor would
not have the throw specifier.
*/
~Error() throw() override {}
#endif
//! returns the error message.
const char* what() const QL_NOEXCEPT override;
private:
ext::shared_ptr<std::string> message_;
};
Why is the member variable ext::shared_ptr<std::string> and not just plain std::string? What reason could there be to heap-allocate the string object itself? (The QuantLib code base seems to heap-allocate just about everything just about always just about everywhere, and pulls in shared_ptr's to cope with that - a classic anti-pattern - but doing it here as well "just for consistency" strikes me as a bit much. Am I missing something?)
This is following the behavior of standard library exception types.
They are supposed to be copyable without throwing exceptions, since throwing an exception during construction of an exception handler parameter would cause a call to std::terminate (and possibly in some other situations requiring a copy of the exception as well).
If std::string was used directly, copying the exception could cause for example a std::bad_alloc to be thrown. Using a reference-counted pointer instead avoids that.
I'm trying to write an exception class that needs to be thrown when a system call fails. The exception should have a developer message and the errno code, and it's what method should format the developer message along with the error code. The C way to do the formatting is snprintf, but I'm trying to avoid that. I tried defining a class member for the exception of type std::stringstream. However, that did not work since stringstream has a private copy constructor. Looking for an alternative I learned about Boost's format object. I tried using it and got a different error:
In file included from tun_device.cc:7:0:
system_error.h:9:7: error: looser throw specifier for ‘virtual SystemError::~SystemError()’
class SystemError : public exception
^
In file included from system_error.h:4:0,
from tun_device.cc:7:
/usr/include/c++/4.8/exception:64:13: error: overriding ‘virtual std::exception::~exception() throw ()’
virtual ~exception() _GLIBCXX_USE_NOEXCEPT;
The way to solve this was to define my own destructor:
~SystemError() throw() {
}
As I understand, this line specifies that the destructor of this exception should not throw any exceptions.
Here's the complete class:
class SystemError : public exception
{
public:
int m_errno;
const char * m_message;
SystemError(int err, const char * message) :
fmt("%1%: %2%") {
fmt % message % errno;
m_errno = err;
this->m_message = message;
}
const char * what() const throw(){
return fmt.str().c_str();
}
~SystemError() throw() {
}
private:
format fmt;
};
I have several questions:
First of all - Am I reinventing the wheel? Is already there a recommended C++ way to handle failed system calls?
Why does using the format class as a member of the exception forces me to override the default destructor?
Is there any pitfall I should be aware of now that I added my own destructor?
Is there a way to achieve what I want using only the standard C++ library?
Exception can be handled using the standard exception class or creating your own classes derived from std::exception class. Inheritance would be used when you would want to extend the already available functionality available using std::exception. So the decision is totally dependent on how you want design your application.
boost::format does not force you to override the destructor. If you notice you are deriving from std::exception and composing boost::format. std::exception destructor is declared as virtual and has a no throw nature.
virtual ~exception() throw();
When you leave out the destructor, compiler implicitly provides a destructor, but this destructor does not have no throw() nature, hence compile error:
format.cpp:5: error: looser throw specifier for âvirtual SystemError::~SystemError()â
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/exception:63: error: overriding âvirtual std::exception::~exception() throw ()â
When you provide a constructor but as:
~SystemError(); //since the base class std::exception has a destrutor with no throw, the child should also follow the same, and again in this case compile time error is received:
format.cpp:25: error: looser throw specifier for âvirtual SystemError::~SystemError()â
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/exception:63: error: overriding âvirtual std::exception::~exception() throw ()â
To resolve the error SystemError should define a destructor like this:
~SystemeError() throw();
Sample SSCCE code:
#include <iostream>
#include<boost/format.hpp>
class SystemError : public std::exception
{
public:
int m_errno;
const char * m_message;
SystemError(int err, const char * message) :
fmt("%1%: %2%") {
fmt % message % err;
m_errno = err;
this->m_message = message;
}
const char * what() const throw(){
return fmt.str().c_str();
}
~SystemError() throw() {
}
// ~SystemError() {
//
// }
private:
boost::format fmt;
};
int main(){
return 0;
}
Adding destructor is like taking responsibilities of your actions. Destructor could be used to clear any heap memory assigned in the class. Absence of destructor would lead compiler to provide an implicit destructor, which could be cause of issues in specific cases.
The compilation error will not be received if the class in discussion has primitive data types.
I'm writing a function, wd_sprintf, to provide a sprintf-like API. Under the covers, it uses the boost library.
If the user of wd_sprintf codes the format string improperly, boost::format will throw an exception. I'd like for my function to intercept the exception, repackage it in a message that identifies wd_sprintf as the locus of the error, and rethrows the exception.
What I can't figure out is what to catch, and how to extract the message.
// wd_sprintf(pattern [,args...]):
//
// This creates a temporary boost::format from pattern, and calls
// wd_sprintf_r() to recursively extract and apply arguments.
#include <boost/exception/all.hpp>
class wd_sprintf_exception : std::runtime_error {
public:
wd_sprintf_exception(string const& msg : std::runtime_error(msg) {}
};
template <typename... Params>
string
wd_sprintf (const string &pat, const Params&... parameters) {
try {
boost::format boost_format(pat);
return wd_sprintf_r(boost_format, parameters...);
}
catch (boost::exception e) {
const string what = string("wd_sprintf: ") + string(e.what());
throw wd_sprintf_exception(what);
}
}
Of course, this gets a compilation error because boost::exception is abstract.
(I've been to a number of sites and pages, including this one whose title was similar but which was full of '<<' operators inserting into a function call, template constructs like boost::get_error_info<my_tag_error_info>(e), and generally much more complexity than I suspect is really needed. I just need the above to work.)
You can't have an an automatic variable of an abstract type. You can, however, have a reference or pointer to one. The reason for this is that the compiler has no way of knowing exactly which derived type the variable actually is, so it doesn't know how much space to allocate for it or which class's copy constructor to use.
When you catch a boost::exception by value, as you're doing, the compiler has to make a local copy of it in your catch block; which it doesn't have enough information to do!
In your specific case, the best solution is to catch a reference to the original exception.
In regards to catching exceptions from Boost.Format, it throws exceptions derived from boost::io::format_error, which is derived from std::exception, not boost::exception. You should be catching boost::io::format_error.
I am using Boost exception_ptr's and observe that rethrow_exception(ptr) does not give me the original exception. I've cooked it down to this:
struct error : virtual std::exception, virtual boost::exception {};
try {
boost::exception_ptr ptr(boost::copy_exception(error()));
boost::rethrow_exception(ptr);
}
catch(boost::exception& e) {
// e is a boost::exception_detail::clone_impl<error>
}
Shouldn't e be of type error instead of type clone_impl?
I am using Boost 1.49.0.
It is by design.
See http://www.boost.org/doc/libs/1_55_0/libs/exception/doc/frequently_asked_questions.html, section "Why is boost::exception abstract?"
The type of boost::exception is abstract to prevent user from "rethrowing" it. If user wants to rethrow, she is forced to use code like
catch( boost::exception & e )
{
e << foo_info(foo);
throw; //Okay, re-throwing the original exception object.
}
You can also look at this from a different perspective. The customer error type can be almost anything, it may not allow derivation from it or may be non-copyable or non-constructable at all (e.g. private constructors only accessible to friends). Therefore, Boost cannot assume anything about customer's type, cannot copy or derive/copy from it and can only keep a pointer to the existing object passed to boost::copy_exception.
I have run into broken compiler, which does not allow exceptions to inherit from std::exception (nvcc 3.0).
so had to create workaround:
struct exception {
explicit exception(const char* message) {
what_ = message;
}
virtual const char *what() const throw() { return what_; }
operator std::exception() const {
return std::runtime_error(what_);
}
private:
const char* what_;
};
struct configuration_error : exception {
configuration_error(const char* message)
: exception(message) {}
};
is there something I am going to lose by not inheriting from exception, instead providing cast? is what necessary in the above case?
thank you
catch (std::exception) will not catch your exception, and you cannot dynamic_cast your exception to std::exception either. If your program never does either of those things, you're fine.
Personally I would not use a compiler this broken, though.
You should upgrade to CUDA 3.1.
If you're trying to create an instance of something derived from std::exception on the device, it won't work because the std::exception constructor would need to be called, and that is not a device function.
Throwing and catching your own type is probably the solution. Since it probably will never make it back to host code, though (C++ doesn't really handle throwing multiple exceptions in parallel), compatibility with std::exception shouldn't be too much of an issue.