[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Preventing implicit calling of non-explicit constructor.

jason.cipriani@gmail.com

12/3/2008 1:57:00 AM

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
18 Answers

Alan Johnson

12/3/2008 3:58:00 AM

0

jason.cipriani@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

std::exception doesn't have a constructor that takes a const char *.
It's full definition according to 18.6.1 is:

namespace std {
class exception {
public:
exception() throw();
exception(const exception&) throw();
exception& operator=(const exception&) throw();
virtual Ì?exception() throw();
virtual const char* what() const throw();
};
}

Seems like you've found an error in Microsoft's implementation.

Anyway, the workaround is to exploit the fact that only one implicit
conversion is allowed. Create a class to wrap a standard exception:

class ExceptionWrapper
{
public:
ExceptionWrapper(const std::exception & e) : m_ref(e)
{}

const std::exception & get() const
{
return m_ref;
}
private:
const std::exception & m_ref;
};


Then change your exception class's interface to accept that:

class AppException {
public:
...
AppException (const char *msg, ...);
AppException (const ExceptionWrapper &cause, const char *msg, ...);
...
};

Within the AppException class use ExceptionWrapper::get to access the
exception.

You can still pass a std::exception as the first argument because an
ExceptionWrapper can be implicitly created, but because only one
implicit conversion is allowed, there is no way for the second
constructor to match a call with const char * as the first argument.

--
Alan Johnson

Salt_Peter

12/3/2008 4:01:00 AM

0

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.

jason.cipriani@gmail.com

12/3/2008 5:44:00 AM

0

On Dec 2, 10:58 pm, Alan Johnson <aw...@yahoo.com> wrote:
> 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
>
> std::exception doesn't have a constructor that takes a const char *.
> It's full definition according to 18.6.1 is:
>
> namespace std {
>    class exception {
>    public:
>       exception() throw();
>       exception(const exception&) throw();
>       exception& operator=(const exception&) throw();
>       virtual  ~exception() throw();
>       virtual const char* what() const throw();
>    };
>
> }
>
> Seems like you've found an error in Microsoft's implementation.

Indeed. After preprocessing, this is what is in MS's <exception>:

class __declspec(dllimport) exception {
public:
exception();
exception(const char *const&);
exception(const char *const&, int);
exception(const exception&);
exception& operator=(const exception&);
virtual ~exception();
virtual const char * what() const;
private:
const char *_m_what;
int _m_doFree;
};

I never noticed that before. It is also documented as such:

http://msdn.microsoft.com/en-us/librar...(VS.80).aspx

Weird.

> Anyway, the workaround is to exploit the fact that only one implicit
> conversion is allowed.  Create a class to wrap a standard exception:

Hey, nice idea, thanks! It was easy to implement and solved the
problem nicely. :-)

Thanks,
Jason


> class ExceptionWrapper
> {
> public:
>      ExceptionWrapper(const std::exception & e) : m_ref(e)
>      {}
>
>      const std::exception & get() const
>      {
>          return m_ref;
>      }
> private:
>      const std::exception & m_ref;
>
> };
>
> Then change your exception class's interface to accept that:
>
> class AppException {
> public:
>      ...
>      AppException (const char *msg, ...);
>      AppException (const ExceptionWrapper &cause, const char *msg, ...);
>      ...
>
> };
>
> Within the AppException class use ExceptionWrapper::get to access the
> exception.
>
> You can still pass a std::exception as the first argument because an
> ExceptionWrapper can be implicitly created, but because only one
> implicit conversion is allowed, there is no way for the second
> constructor to match a call with const char * as the first argument.
>
> --
> Alan Johnson

jason.cipriani@gmail.com

12/3/2008 5:46:00 AM

0

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

jason.cipriani@gmail.com

12/3/2008 5:51:00 AM

0

On Dec 3, 12:46 am, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.com> wrote:
> 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.

runtime_error*

Evertjan.

6/17/2014 1:17:00 PM

0

I wrote on 17 jun 2014 in soc.culture.jewish.moderated:
> Herman Rubin <hrubin@skew.stat.purdue.edu> wrote on 17 jun 2014 in
> soc.culture.jewish.moderated:
>
>> I asked earlier, with the heading "Kaddish", where in the Torah
>> does it say that a Jew cannot stop being a Jew. I know of no
>> such statement or statements leading to this in the Torah, so
>> again I ask for a reference to such.
>
> Probably it does not. But why should it to be a rule?
>

But why should it be form the Torah to be a rule?, I ment.

--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)

Evertjan.

6/17/2014 4:14:00 PM

0

Giorgies E Kepipesiom <kepipesiom@hotmail.com> wrote on 17 jun 2014 in
soc.culture.jewish.moderated:

> On Monday, June 16, 2014 8:58:20 PM UTC-4, Evertjan. wrote:
>>
>> There is more to Haloche than "just" Torah.
>>
> Says someone who is a real expert in Haloche and in Torah.

So one has to be an expert to say something?

If you think it is not true, why not give valid arguments?

Is Haloche only Toureh in your view,
oh sorry, in your esteemed expert opinion?

If so, why?

I think Jewish discussion is or should be free of argument by status.

--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)

Herman Rubin

6/18/2014 12:09:00 AM

0

On 2014-06-17, Evertjan. <exxjxw.hannivoort@inter.nl.net> wrote:
> I wrote on 17 jun 2014 in soc.culture.jewish.moderated:
>> Herman Rubin <hrubin@skew.stat.purdue.edu> wrote on 17 jun 2014 in
>> soc.culture.jewish.moderated:

>>> I asked earlier, with the heading "Kaddish", where in the Torah
>>> does it say that a Jew cannot stop being a Jew. I know of no
>>> such statement or statements leading to this in the Torah, so
>>> again I ask for a reference to such.

>> Probably it does not. But why should it to be a rule?


> But why should it be form the Torah to be a rule?, I ment.

For one thing, someone posted that it is from the Torah.
So I asked, where?

For another, many religious Jews, including most American,
do not accept the authority of anything else without direct
justification. This rule was essentially initiated in the
time of Ezra, according to the Tanakh, and as far as I can
tell from the writings, that is it. Ezra was also the one
who ended the existence of n'viim as "unnecessary"; I see
no evidence of this latter.


--
This address is for information only. I do not claim that these views
are those of the Statistics Department or of Purdue University.
Herman Rubin, Department of Statistics, Purdue University
hrubin@stat.purdue.edu Phone: (765)494-6054 FAX: (765)494-0558

Evertjan.

6/18/2014 10:55:00 AM

0

Herman Rubin <hrubin@skew.stat.purdue.edu> wrote on 18 jun 2014 in
soc.culture.jewish.moderated:

> On 2014-06-17, Evertjan. <exxjxw.hannivoort@inter.nl.net> wrote:
>> I wrote on 17 jun 2014 in soc.culture.jewish.moderated:
>>> Herman Rubin <hrubin@skew.stat.purdue.edu> wrote on 17 jun 2014 in
>>> soc.culture.jewish.moderated:
>
>>>> I asked earlier, with the heading "Kaddish", where in the Torah
>>>> does it say that a Jew cannot stop being a Jew. I know of no
>>>> such statement or statements leading to this in the Torah, so
>>>> again I ask for a reference to such.
>
>>> Probably it does not. But why should it to be a rule?
>
>
>> But why should it be form the Torah to be a rule?, I ment.
>
> For one thing, someone posted that it is from the Torah.
> So I asked, where?
>
> For another, many religious Jews, including most American,
> do not accept the authority of anything else without direct
> justification. This rule was essentially initiated in the
> time of Ezra, according to the Tanakh, and as far as I can
> tell from the writings, that is it. Ezra was also the one
> who ended the existence of n'viim as "unnecessary"; I see
> no evidence of this latter.

Herman, I did not disagree with you.

Personally I do not accept authority per se period.
For me doubt is the only truth.

But that does not mean I/we cannot discuss the Haloche.

I don't accept the rules of chess as final and everlasting,
I heve severe doubts about the "en passant" rule,
but discussing it remains possible and enjoyable,
and for playing chess it is necessary, well rather,
to temporarily hold to those rules.

Joy should be the prime objective of discussion.

I do not claim my views are constant
or the views of this NG,
let alone any Statistics Department.

--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)

Herman Rubin

6/18/2014 7:43:00 PM

0

On 2014-06-18, mm <mm2005@bigfoot.com> wrote:
> On Tue, 17 Jun 2014 23:34:55 +0000 (UTC), Herman Rubin
><hrubin@skew.stat.purdue.edu> wrote:

>>On 2014-06-17, Evertjan. <exxjxw.hannivoort@inter.nl.net> wrote:
>>> Herman Rubin <hrubin@skew.stat.purdue.edu> wrote on 17 jun 2014 in
>>> soc.culture.jewish.moderated:

..................

>>I doubt that this was the case in the days of the First Temple. Herod's
>>mother was an Israelite.

> How does his mother being an Israelite in any way suggest that the rule
> wasn't the same earlier?

> What does Herod have to do with hit at all?

If maternal descent wree the case then, Herod would have been
a Jew. The accounts in the Tanakh do not indicate that this was
the case.

> And how do you go from Herod all the way back to the First Temple in one
> jump?

Can you give me an example from Tanakh in that period indicating
othewise? There is also the case of the captured woman; one
would question whether the soldier's children would not be Jews,
as the woman becaqme a wife with full rights.

......................


--
This address is for information only. I do not claim that these views
are those of the Statistics Department or of Purdue University.
Herman Rubin, Department of Statistics, Purdue University
hrubin@stat.purdue.edu Phone: (765)494-6054 FAX: (765)494-0558