Re: Preventing implicit calling of non-explicit constructor.
On Dec 2, 11:00 pm, Salt_Peter <pj_h...@yahoo.com> wrote:
On Dec 2, 8:57 pm, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.com> wrote:
I have an application with a class "AppException" derived from
std::exception. I have full control over the implementation of
"AppException". I have two constructors like this:
class AppException {
public:
...
AppException (const char *msg, ...);
AppException (const std::exception &cause, const char *=
msg, ...);
...
};
The first constructor takes a printf format string and optional
parameters. The second takes an std::exception as the root cause, and
the same printf-style message. This functionality is critical (I need
to be able to construct an AppException from just a message, or from a
message and an std::exception root cause), although this particular
interface is not critical.
My problem is that std::exception has a non-explicit const char *
constructor. Therefore it can be implicitly converted from a const
char *. So in cases where I am using the no-cause constructor but
where my format parameters are a single additional string, e.g.:
throw AppException("Some string: %s", someString);
The compiler (VS 2008's compiler) complains that both constructors are
possible matches (the second constructor also matches, it attempts to
implicitly convert the const char * to an std::exception, and pass
someString as "msg").
How can I get rid of this ambiguity, but still keep the same
functionality? I'm kind of frazzled and having trouble coming up with
ideas. If I could somehow say that I wanted std::exception(const char
*) to be explicit, that would be one way to solve the problem, but I
don't think that's possible.
Thanks,
Jason
#include <iostream>
#include <stdexcept>
class AppException : public std::runtime_error
{
public:
AppException(const char* s)
: std::runtime_error(s) { }
// other ctors
};
int main()
{
try
{
throw AppException("testing AppException");
}
catch( std::exception& r_e )
{
std::cout << "Error: ";
std::cout << r_e.what() << std::endl;
}
}
/*
Error: testing AppException
*/
std::runtime_error is itself a derivative of std::exception and has an
explicit constructor. Consider std::logic_error, std::out_of_range,
std::domain_error, etc as well should you plan to specialize your
exceptions.
Thanks for the tip. This doesn't solve my problem, as I still want to
be able to use any std::exception as the "cause", not just a
runtime_exception. Still, I've modified it to derive from
runtime_exception anyways, as it definitely seems more appropriate.
Jason