Reputation: 4706
I came across the following code on VS2008
if (!CreateProcess( NULL,
const_cast<LPWSTR>(ss.str().c_str()),
NULL,
NULL,
FALSE,
CREATE_NO_WINDOW|NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&si,
&pi))
{
throw std::exception("Unable to format Device");
}
Now I am porting the code to mingw gcc and I get the error
error: no matching function for call to 'std::exception::exception(const char [23])'
Investigating the issue I noticed that Visual Studio has a file exception which does have an exception class and does take in char*. Some of the definitions look like this
__CLR_OR_THIS_CALL exception();
__CLR_OR_THIS_CALL exception(const char *const&);
__CLR_OR_THIS_CALL exception(const char *const&, int);
__CLR_OR_THIS_CALL exception(const exception&);
exception& __CLR_OR_THIS_CALL operator=(const exception&);
virtual __CLR_OR_THIS_CALL ~exception();
virtual const char * __CLR_OR_THIS_CALL what() const;
My question is how should I circumvent this build issue on mingw gcc ? Should I create a new class that inherits from std::runtime_error and throw that instead ?
Upvotes: 34
Views: 24762
Reputation: 44023
Opinion plays a role here. The problem is that std::exception
does not have a constructor that takes a string argument; this is an MSVC extension. I see two ways to go about it:
std::exception
The first case is straightforward; just use
throw std::exception();
The drawback is that you don't get a descriptive error message.
If the error message is important, using std::exception
directly is not an option. In this case, you could use either std::logic_error
or std::runtime_error
, which inherit std::exception
and do have constructors taking a string argument, so
throw std::runtime_error("Unable to format Device");
might already solve the problem. catch
clauses that caught the std::exception
will also catch the std::runtime_error
. There is one potential problem, though: catch
clauses that catch std::runtime_error
would not have caught the std::exception
but will catch this one.
This seems like a bit of a corner case, and it is entirely possible that it is not a problem for you. If, however, there is a possibility that along the call stack there is a catch
clause that catches std::runtime_error
but should not catch the exception thrown by this code, you could derive your own exception class from std::exception
that does take a string argument. Because the class is new, it will not be caught by existing catch
clauses. For example:
class descriptive_exception : public std::exception {
public:
descriptive_exception(std::string const &message) : msg_(message) { }
virtual char const *what() const noexcept { return msg_.c_str(); }
private:
std::string msg_;
}
And then
throw descriptive_exception("Unable to format Device");
This is arguably not very pretty, and it is unlikely that it is necessary, so the more probable solution is to use std::runtime_error
or std::logic_error
(or a class derived from one of them).
Whether std::logic_error
or std::runtime_error
is more appropriate is not very clear-cut; in this case I'd probably go with std::runtime_error
because the error does not seem even theoretically predictable, but given that std::domain_error
and std::future_error
derive from std::logic_error
, it would not be entirely out of place in that hierarchy. This is, I think, a matter of opinion.
Upvotes: 82