Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-22 Thread Terje Slettebø
>From: "David Abrahams" <[EMAIL PROTECTED]>

> Terje Slettebø <[EMAIL PROTECTED]> writes:
>
> >> What I meant (though sorry I was probably too blunt about it) was that
> >> it's irrelevant whether you actually observed termination or not,
> >> unless you're intending for lexical_cast to work just on that compiler.
> >
> > That's correct, and I meant nothing else, either.
>
> If you understood all along that the copy ctor of your exception class
> could cause termination when the exception was thrown, I don't
> understand why I went through this long twisty discussion just to have
> you tell me so.

What happened was:

1. You told me it could cause termination.
2. I made a test case, and observed that it didn't cause termination on
construction, and that due to the implementation, no copy was made, so it
didn't test the copying (which may cause termination).
3. You said it was irrelevant that no termination was observed.
4. I said that I hadn't claimed the test proved there would be no
termination, since on that platform, the copying wasn't tested.

As you can see, I agreed with you from the beginning. It just seems that you
thought I claimed that since it didn't terminate, it wouldn't do that on any
platform. I didn't mean that, and it seems this misunderstanding was the
cause of this long discussion.

> > I wouldn't have made this such a big issue had you not claimed the
> > implementation didn't do what was requested, when both that and your
> > suggestion implements the request.
>
> I think there's a stronger argument for type_info being a
> representative of the type, because among other things an
> implementation is allowed to have type_info::name() return the empty
> string for all types.

I don't disagree with that. I merely made the point that my implementation
also fulfilled the request, which it seems you now agree to, as well.

I also think returning the type as type_info is better.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-22 Thread David Abrahams
Terje Slettebø <[EMAIL PROTECTED]> writes:

>> What I meant (though sorry I was probably too blunt about it) was that
>> it's irrelevant whether you actually observed termination or not,
>> unless you're intending for lexical_cast to work just on that compiler.
>
> That's correct, and I meant nothing else, either.

If you understood all along that the copy ctor of your exception class
could cause termination when the exception was thrown, I don't
understand why I went through this long twisty discussion just to have
you tell me so.  If I caused the twisting, I'm sorry.  I didn't mean
for this to get so complicated.

> No, it doesn't; it stores a reference to an object describing them. My
> version stored a string describing them. I just applied the same
> hair-splitting reasoning that made you categorically state that my
> implementation "didn't do that" (what was quoted as requested). My
> implementation do it just as well as your suggestion, both stores
> information describing the types. One is geared towards user-readable
> information, one is geared towards program-readable information. Agree?
>
> I wouldn't have made this such a big issue had you not claimed the
> implementation didn't do what was requested, when both that and your
> suggestion implements the request.

I think there's a stronger argument for type_info being a
representative of the type, because among other things an
implementation is allowed to have type_info::name() return the empty
string for all types.

However, I'm not going to press this issue any further.  

I was just trying to make a simple point that the copy ctor of an
exception object should not throw exceptions.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-22 Thread Terje Slettebø
>From: "David Abrahams" <[EMAIL PROTECTED]>

> Terje Slettebø <[EMAIL PROTECTED]> writes:
>
> >> >> > As it stands, it prints "Exception - Constructor", as it throws
> >> >> > an exception in the constructor of the Exception exception. If
> >> >> > the throw-statement in the constructor is commented out, it
> >> >> > prints "Exception - Exception", apparently not invoking the copy
> >> >> > constructor when throwing the exception (which it's allowed to).
> >> >>
> >> >> Irrelevant.  A program that invokes undefined behavior may appear to
> >> >> work fine also.
> >
> > I did not state the latter part as a general claim, which is why I said
that
> > eliding the copy is something it's allowed to, but not required to.
Thus,
> > there's no argument to consider "irrelevant".
>
> What I meant (though sorry I was probably too blunt about it) was that
> it's irrelevant whether you actually observed termination or not,
> unless you're intending for lexical_cast to work just on that compiler.

That's correct, and I meant nothing else, either.

> >> > The reason the extended error type was added, was that there has
> >> > been requests on this list for storing the types used in the
> >> > conversion, in the exception, to make it easier to know which
> >> > conversion failed.
> >>
> >> That's a good request, but you didn't do that, did you?
> >
> > Let me rephrase it: IIRC, the request was for storing information about
the
> > types used, not how this was to be done. Thus, whether or not this does
what
> > was requested depends on how to interpret the request.
> >
> > The suggestion to store (pointer/reference to) type_info objects doesn't
> > store the types, either; it stores information about them, this time in
a
> > way easier for the program to use.
> >
> > So, I can just as well say as you say: The suggestion you said you meant
> > (storing references to type_info objects) doesn't do that, either, does
it?
>
> Ugh.  As far as it's possible to store a type at all in C++, yes my
> suggestion does store the types.

No, it doesn't; it stores a reference to an object describing them. My
version stored a string describing them. I just applied the same
hair-splitting reasoning that made you categorically state that my
implementation "didn't do that" (what was quoted as requested). My
implementation do it just as well as your suggestion, both stores
information describing the types. One is geared towards user-readable
information, one is geared towards program-readable information. Agree?

I wouldn't have made this such a big issue had you not claimed the
implementation didn't do what was requested, when both that and your
suggestion implements the request.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-22 Thread David Abrahams
Terje Slettebø <[EMAIL PROTECTED]> writes:

>> >> > As it stands, it prints "Exception - Constructor", as it throws
>> >> > an exception in the constructor of the Exception exception. If
>> >> > the throw-statement in the constructor is commented out, it
>> >> > prints "Exception - Exception", apparently not invoking the copy
>> >> > constructor when throwing the exception (which it's allowed to).
>> >>
>> >> Irrelevant.  A program that invokes undefined behavior may appear to
>> >> work fine also.
>
> I did not state the latter part as a general claim, which is why I said that
> eliding the copy is something it's allowed to, but not required to. Thus,
> there's no argument to consider "irrelevant".

What I meant (though sorry I was probably too blunt about it) was that
it's irrelevant whether you actually observed termination or not,
unless you're intending for lexical_cast to work just on that compiler.

>> Just use a string literal; the compiler has to allocate that as part
>> of the program image.
>
> Sure, that's what the original lexical_cast did. However, if you are to
> include in the string info about the types, storing it as a string literal
> is not enough.

No, but you could store 3 char const*s, using type_info::name() for
two of them.

>> > The reason the extended error type was added, was that there has
>> > been requests on this list for storing the types used in the
>> > conversion, in the exception, to make it easier to know which
>> > conversion failed.
>>
>> That's a good request, but you didn't do that, did you?
>
> Let me rephrase it: IIRC, the request was for storing information about the
> types used, not how this was to be done. Thus, whether or not this does what
> was requested depends on how to interpret the request.
>
> The suggestion to store (pointer/reference to) type_info objects doesn't
> store the types, either; it stores information about them, this time in a
> way easier for the program to use.
>
> So, I can just as well say as you say: The suggestion you said you meant
> (storing references to type_info objects) doesn't do that, either, does it?

Ugh.  As far as it's possible to store a type at all in C++, yes my
suggestion does store the types.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0(mostlylexical_cast.hpp)

2003-03-22 Thread David Abrahams
Kevlin Henney <[EMAIL PROTECTED]> writes:

>>Yes. Since type_info objects can't be copied, one might instead store
>>pointers or references to them. 
>
> Pointers would be better because, for better or for worse (mostly for
> worse), standard exceptions support assignment as part of their
> interface.

Why should boost exception classes behave like std:: exception
classes in this regard?

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-22 Thread Terje Slettebø
>From: "David Abrahams" <[EMAIL PROTECTED]>

> Terje Slettebø <[EMAIL PROTECTED]> writes:
>
> >> Terje Slettebø <[EMAIL PROTECTED]> writes:
> >>
> >> > I've tried the program below on Intel C++ 7.0 and MSVC 6, and I
haven't got
> >> > it to call terminate(). It may be that it doesn't handle exceptions
> >> > correctly, though.
> >>
> >> Because you are not running in a low-memory condition.
> >
> > What difference would that make? In the example program, it throws an
> > exception from the exception constructor, effectively simulating an
> > out-of-memory exception.
>
> Replace operator new so that it throws unconditionally *after* the
> exception object is constructed.  If you try this on an implementation
> where the exception object gets copied during unwinding, it will
> terminate().  It's the copy ctor that matters in this case.

The test program also had a throwing copy constructor. However, on Intel C++
7.0, the copy was elided, so the copy didn't get tested.

> >> > As it stands, it prints "Exception - Constructor", as it throws
> >> > an exception in the constructor of the Exception exception. If
> >> > the throw-statement in the constructor is commented out, it
> >> > prints "Exception - Exception", apparently not invoking the copy
> >> > constructor when throwing the exception (which it's allowed to).
> >>
> >> Irrelevant.  A program that invokes undefined behavior may appear to
> >> work fine also.

I did not state the latter part as a general claim, which is why I said that
eliding the copy is something it's allowed to, but not required to. Thus,
there's no argument to consider "irrelevant".

> >> >> What's wrong with char const*?
> >> >
> >> > You mean storing the string as a character array?
> >>
> >> No, I mean not storing the string at all (char const* is not an
> >> array), but storing an array is another option.
> >
> > Yes, I know that, of course. However, since if you just store a
> > pointer, the string has to be allocated some other way. How would
> > you allocate it?
>
> Just use a string literal; the compiler has to allocate that as part
> of the program image.

Sure, that's what the original lexical_cast did. However, if you are to
include in the string info about the types, storing it as a string literal
is not enough.

> > As Kevlin says in another posting, the "terminate on second
> > exception",
>
> He never used that phrase.  What do you mean?

True. I was referring to "In an insufficient-memory condition the former
will result in a bad_alloc being thrown and in the latter a call to
terminate." In other words, if you throw an exception in the copy
constructor, when an exception has already been thrown, i.e. during stack
unwinding, as you also say in the updated "Error and Exception Handling"
document.

> > which I thought you alluded to in your first reply, and maybe you
> > did, may not apply at the point of construction, since it only
> > applies after the evaluation of the throw-expression. In other
> > words, if the construction fails, you only loose the first
> > exception, and it instead throws the new one.
>
> I am aware of how C++ EH works, really!

I know you are. This was mostly to try to get a common understanding, since
I was a little confused about what you meant, and therefore wrote the above,
explaining what I had meant.

> > The reason the extended error type was added, was that there has
> > been requests on this list for storing the types used in the
> > conversion, in the exception, to make it easier to know which
> > conversion failed.
>
> That's a good request, but you didn't do that, did you?

Let me rephrase it: IIRC, the request was for storing information about the
types used, not how this was to be done. Thus, whether or not this does what
was requested depends on how to interpret the request.

The suggestion to store (pointer/reference to) type_info objects doesn't
store the types, either; it stores information about them, this time in a
way easier for the program to use.

So, I can just as well say as you say: The suggestion you said you meant
(storing references to type_info objects) doesn't do that, either, does it?


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0(mostlylexical_cast.hpp)

2003-03-22 Thread Kevlin Henney
In message <[EMAIL PROTECTED]>, Terje Slettebø
<[EMAIL PROTECTED]> writes
>>From: "Kevlin Henney" <[EMAIL PROTECTED]>
>
>> However, the decision as to whether this should be in the 'what' string
>> is perhaps one that can be revisited.
>
>Indeed. :)
>
>I wasn't sure what kind of interface to use for this, so I just made it part
>of the what() string.

I am not a great fan of embedding programmer-specific info in exception
text messages as it is unobtainable by the programmer except in a debug
situation -- the correctness of a program should not rely on debugging
:-> -- and such precision is of less use to other users.

>> It would be feasible to avoid any
>> allocation issues at all by leaving the human readable string as general
>> as it was before and adding type_info members that described the source
>> and target types.
>
>Yes. Since type_info objects can't be copied, one might instead store
>pointers or references to them. 

Pointers would be better because, for better or for worse (mostly for
worse), standard exceptions support assignment as part of their
interface.

>This appears to need yet another inheritance
>layer, though, unless the virtual functions for accessing the type_info
>objects are made part of bad_lexical_cast. 

Not necessarily. It would be reasonable to fold up the inheritance
again, and simply provide a two argument constructor and a concrete
implementation:

class bad_lexical_cast : public std::bad_cast
{
public:
bad_lexical_cast()
: source(&typeid(void)), target(&typeid(void))
{
}
bad_lexical_cast(
const std::type_info &source,
const std::type_info &target)
: source(&source), target(&target)
{
}
const std::type_info &source_type() const
{
return *source;
}
const std::type_info &target_type() const
{
return *target;
}
virtual const char *what() throw()
{
return  "bad_lexical_cast: ...";
}
virtual ~bad_lexical_cast() throw()
{
}
private:
const std::type_info *source;
const std::type_info *target;
};

The default constructor would be there for backward compatibility only
(in case anyone had decided to throw bad_lexical_cast in their own
code), but would be deprecated with immediate effect.

>> (2) Rollback the design to something closer to the original, ie a fixed-
>> string literal message as the result of calling 'what', and provide
>> supplementary information for handlers that care enough to catch a
>> bad_lexical_cast.
>
>I think this is a good solution, and it eliminates any throws from the
>exception. This may also be a more flexible solution, as the type_info
>objects may be used directly, in any custom error message.

Yes, this was my preferred option. My least favourite, which I didn't
list at all, was using an array.

Kevlin


  Kevlin Henney   phone:  +44 117 942 2990
  mailto:[EMAIL PROTECTED] mobile: +44 7801 073 508
  http://www.curbralan.comfax:+44 870 052 2289
  Curbralan: Consultancy + Training + Development + Review

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-22 Thread David Abrahams
Terje Slettebø <[EMAIL PROTECTED]> writes:

>> Terje Slettebø <[EMAIL PROTECTED]> writes:
>>
>> >>From: "David Abrahams" <[EMAIL PROTECTED]>
>> >
>> >> Are you saying that you have defined an exception with a std::string
>> >> member?  That's VERY bad!  Throwing that exception can lead directly
>> >> to termination!
>> >
>> > You mean if the exception itself throws during construction or copying?
>>
>> Yes.
>>
>> > I've tried the program below on Intel C++ 7.0 and MSVC 6, and I haven't got
>> > it to call terminate(). It may be that it doesn't handle exceptions
>> > correctly, though.
>>
>> Because you are not running in a low-memory condition.
>
> What difference would that make? In the example program, it throws an
> exception from the exception constructor, effectively simulating an
> out-of-memory exception.

Replace operator new so that it throws unconditionally *after* the
exception object is constructed.  If you try this on an implementation
where the exception object gets copied during unwinding, it will
terminate().  It's the copy ctor that matters in this case.

>> > As it stands, it prints "Exception - Constructor", as it throws
>> > an exception in the constructor of the Exception exception. If
>> > the throw-statement in the constructor is commented out, it
>> > prints "Exception - Exception", apparently not invoking the copy
>> > constructor when throwing the exception (which it's allowed to).
>>
>> Irrelevant.  A program that invokes undefined behavior may appear to
>> work fine also.
>
> You said that it may terminate the program. I assumed from that that you
> meant it would call terminate(). 

Yes.  If the copy ctor were called, which as you say it's allowed to.

> Did you instead mean undefined behaviour?  

No.

> If so, how? And how would that be related to terminating the
> program? As you say, anything can happen with undefined behaviour,
> including the "expected" behaviour.

It's related in that there are any number of ways an incorrect program
may appear to work correctly.  I assert that any program throwing
exception objects containing std::string members is incorrect (for
some reasonable definition of "incorrect").

>> >> What's wrong with char const*?
>> >
>> > You mean storing the string as a character array?
>>
>> No, I mean not storing the string at all (char const* is not an
>> array), but storing an array is another option.
>
> Yes, I know that, of course. However, since if you just store a
> pointer, the string has to be allocated some other way. How would
> you allocate it? 

Just use a string literal; the compiler has to allocate that as part
of the program image.

> If you use "new", won't that bring the same potential problem as
> std::string? This is why I thought you might have meant storing an
> array (as STLPort does it), rather than storing a pointer. Storing
> an array eliminates the possibility of throwing an exception at
> construction.

Not exactly, but anyway...
Throwing at construction is problematic, but it's not the big
problem.  The big problem happens when you throw during copying.

>> There's no guarantee you have readable names anyway.  Finally, you
>> should never format exception messages at the throw point.  An
>> exception whose what() needs to print type names should store the
>> typeids and put the formatting logic in what().
>
> A problem is that what() can't throw, either. So you'd have to wrap it in a
> try-catch. 

Yes, if you insist on trying to format a string there.

> Then there's the issue of what to return from what() if the
> formatting throws.

Yes.  You'd need some fallback strategy.  Big deal; either you
implement the fallback or all your users do.

> As Kevlin says in another posting, the "terminate on second
> exception", 

He never used that phrase.  What do you mean?

> which I thought you alluded to in your first reply, and maybe you
> did, may not apply at the point of construction, since it only
> applies after the evaluation of the throw-expression. In other
> words, if the construction fails, you only loose the first
> exception, and it instead throws the new one.

I am aware of how C++ EH works, really!

> As for throwing in the copy constructor, that might be a problem,

Bingo.

> since the "call by value" semantics of throwing an exception may
> mean that it makes a copy of the exception, after the
> throw-expression is evaluated.

Yes.

> The reason the extended error type was added, was that there has
> been requests on this list for storing the types used in the
> conversion, in the exception, to make it easier to know which
> conversion failed. 

That's a good request, but you didn't do that, did you?  Formatting
them into the what() string is a bad idea unless you are very careful.
See http://www.boost.org/more/error_handling.html

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boos

Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0(mostlylexical_cast.hpp)

2003-03-22 Thread Terje Slettebø
>From: "Kevlin Henney" <[EMAIL PROTECTED]>

> In message <[EMAIL PROTECTED]>, David Abrahams
> <[EMAIL PROTECTED]> writes
> >
> >There's no guarantee you have readable names anyway.
>
> That's a purely theoretical rather than practical consideration. In
> practice, I believe that all of the compilers that lexical_cast works
> under offer something relatively meaningful. The original version of
> lexical_cast simply stated, with a string literal, that the conversion
> had failed. There was some user demand for supplementary information,
> which Terje's version provided.
>
> However, the decision as to whether this should be in the 'what' string
> is perhaps one that can be revisited.

Indeed. :)

I wasn't sure what kind of interface to use for this, so I just made it part
of the what() string.

> It would be feasible to avoid any
> allocation issues at all by leaving the human readable string as general
> as it was before and adding type_info members that described the source
> and target types.

Yes. Since type_info objects can't be copied, one might instead store
pointers or references to them. This appears to need yet another inheritance
layer, though, unless the virtual functions for accessing the type_info
objects are made part of bad_lexical_cast. For example:

// exception used to indicate runtime lexical_cast failure
class bad_lexical_cast : public std::bad_cast
{
public:
virtual const std::type_info &source_type() const throw() = 0;
virtual const std::type_info &target_type() const throw() = 0;

virtual ~bad_lexical_cast() throw()
{
}
};

namespace detail // actual underlying concrete exception type
{
template
class no_lexical_conversion : public bad_lexical_cast
{
public:
virtual const std::type_info &source_type() const throw() {
return typeid(Source); }
virtual const std::type_info &target_type() const throw() {
return typeid(Target); }

virtual ~no_lexical_conversion() throw()
{
}
virtual const char *what() const throw()
{
return "bad lexical cast: "
   "source type value could not be interpreted as
target"
}
};
}

This also addresses the concern of readable type names, and leaves the
what() string as it was.

> This leads to a number of possible options:
>
> (1) Use the static solution, as Terje originally intended, and use the
> current solution only for VC6.
> (2) Rollback the design to something closer to the original, ie a fixed-
> string literal message as the result of calling 'what', and provide
> supplementary information for handlers that care enough to catch a
> bad_lexical_cast.

I think this is a good solution, and it eliminates any throws from the
exception. This may also be a more flexible solution, as the type_info
objects may be used directly, in any custom error message.

> (3) Play around with C-style memory management and allocate arrays on
> demand, being sure to trap any bad outcome.
> (4) Leave as is.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-22 Thread Terje Slettebø
>From: "David Abrahams" <[EMAIL PROTECTED]>

> Terje Slettebø <[EMAIL PROTECTED]> writes:
>
> >>From: "David Abrahams" <[EMAIL PROTECTED]>
> >
> >> Terje Slettebø <[EMAIL PROTECTED]> writes:
> >>
> >> >> C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(74) :
> > warning
> >> > C4512: 'no_lexical_conversion >> > std::char_traits,class std::allocator >,long>' :
assignment
> >> > operator could not be generated
> >> >
> >> > This is due to that it stores a const std::string object, describing
the
> >> > exception
> >>
> >> Are you saying that you have defined an exception with a std::string
> >> member?  That's VERY bad!  Throwing that exception can lead directly
> >> to termination!
> >
> > You mean if the exception itself throws during construction or copying?
>
> Yes.
>
> > I've tried the program below on Intel C++ 7.0 and MSVC 6, and I haven't
got
> > it to call terminate(). It may be that it doesn't handle exceptions
> > correctly, though.
>
> Because you are not running in a low-memory condition.

What difference would that make? In the example program, it throws an
exception from the exception constructor, effectively simulating an
out-of-memory exception.

> > As it stands, it prints "Exception - Constructor", as it throws an
exception
> > in the constructor of the Exception exception. If the throw-statement in
the
> > constructor is commented out, it prints "Exception - Exception",
apparently
> > not invoking the copy constructor when throwing the exception (which
it's
> > allowed to).
>
> Irrelevant.  A program that invokes undefined behavior may appear to
> work fine also.

You said that it may terminate the program. I assumed from that that you
meant it would call terminate(). Did you instead mean undefined behaviour?
If so, how? And how would that be related to terminating the program? As you
say, anything can happen with undefined behaviour, including the "expected"
behaviour.

> >> What's wrong with char const*?
> >
> > You mean storing the string as a character array?
>
> No, I mean not storing the string at all (char const* is not an
> array), but storing an array is another option.

Yes, I know that, of course. However, since if you just store a pointer, the
string has to be allocated some other way. How would you allocate it? If you
use "new", won't that bring the same potential problem as std::string? This
is why I thought you might have meant storing an array (as STLPort does it),
rather than storing a pointer. Storing an array eliminates the possibility
of throwing an exception at construction.

> > Sure, that's possible, and I see that STLPort do it, and it's
> > probably safer, as you say. It does mean you have to specify the
> > maximum string length in advance, though. As "no_lexical_conversion"
> > what() prints out the source and target types, it may truncate long
> > type names.
>
> There's no guarantee you have readable names anyway.  Finally, you
> should never format exception messages at the throw point.  An
> exception whose what() needs to print type names should store the
> typeids and put the formatting logic in what().

A problem is that what() can't throw, either. So you'd have to wrap it in a
try-catch. Then there's the issue of what to return from what() if the
formatting throws.

As Kevlin says in another posting, the "terminate on second exception",
which I thought you alluded to in your first reply, and maybe you did, may
not apply at the point of construction, since it only applies after the
evaluation of the throw-expression. In other words, if the construction
fails, you only loose the first exception, and it instead throws the new
one.

As for throwing in the copy constructor, that might be a problem, since the
"call by value" semantics of throwing an exception may mean that it makes a
copy of the exception, after the throw-expression is evaluated.

The reason the extended error type was added, was that there has been
requests on this list for storing the types used in the conversion, in the
exception, to make it easier to know which conversion failed. It has also
proved useful in the regression testing. bad_lexical_cast was not modified,
to not break the interface, so this type inherits from it.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-22 Thread David Abrahams
Kevlin Henney <[EMAIL PROTECTED]> writes:

> In message <[EMAIL PROTECTED]>, David Abrahams
> <[EMAIL PROTECTED]> writes
>>
>>> I've tried the program below on Intel C++ 7.0 and MSVC 6, and I haven't got
>>> it to call terminate(). It may be that it doesn't handle exceptions
>>> correctly, though.
>>
>>Because you are not running in a low-memory condition.
>
> Not quite: there is a difference between the initial construction and
> the copy. In an insufficient-memory condition with a compiler that
> creates the exception directly, rather than creating and then copying
> it, the exception does not become active until the constructor has
> completed. 

You don't think I know this?

Terje throws an exception, which causes copying.  If the copy throws,
you go directly to terminate().

> If it does not complete, I believe that there is no cause to
> call terminate. MSVC is one such compiler, but BCC is not. In an
> insufficient-memory condition the former will result in a bad_alloc
> being thrown and in the latter a call to terminate.

No, you could run out of memory after initial construction but during
copying.

> Given that the workaround in Terje's code was in response to a VC6
> limitation (static data members of templates don't initialise
> correctly), it may make sense to conditionally compile the code so
> that the current code is used for VC6 and Terje's original is used
> for more capable compilers.

I have serious doubts that this is the best approach.

 What's wrong with char const*?
>>>
>>> You mean storing the string as a character array? 
>>
>>No, I mean not storing the string at all (char const* is not an
>>array), but storing an array is another option.
>
> Storing an array is not a reasonable option in this particular case,
> given what the code is trying to achieve. It is either impractical for
> the application if the bound is too low or can cause undefined behaviour
> if the bound is too high. In other words, unless (or until) the standard
> stipulates a limit it's the wrong design whichever way you look at it
> for this situation.

A limit for what?

>>There's no guarantee you have readable names anyway.  
>
> That's a purely theoretical rather than practical consideration. In
> practice, I believe that all of the compilers that lexical_cast works
> under offer something relatively meaningful. 

"relatively" is a relative term ;-) I guess if you don't mind reading
GCC's mangled names then I am forced to agree.

> The original version of lexical_cast simply stated, with a string
> literal, that the conversion had failed. There was some user demand
> for supplementary information, which Terje's version provided.

That shouldn't be formatted at the throw point.

> However, the decision as to whether this should be in the 'what' string
> is perhaps one that can be revisited. It would be feasible to avoid any
> allocation issues at all by leaving the human readable string as general
> as it was before and adding type_info members that described the source
> and target types.

Yes, that was my suggestion.

>>Finally, you should never format exception messages at the throw
>>point.  An exception whose what() needs to print type names should
>>store the typeids and put the formatting logic in what().
>
> On the whole this is generally good advice, but it should not be
> treated as an absolute. Both lazy and eager evaluation have their
> place in design.

Not for exception what() messages when avoidable.

> If the effect is the same, it does not matter where the string
> is formatted. 

The effect is not the same though.

> In this case, Terje's original intent was to use a static member to
> hold the representation, which would have resulted in formatting the
> string before the constructor, which is the critical point of
> failure. 

How can a static string hope to hold arbitrary messages containing a
variety of type names? Or were you not planning to allow lexical cast
to be used in multithreaded programs?  And given that you have to
format a different message each time the exception is thrown I don't
see how you can format the string *before* the constructor runs
without user-intervention!  And even if you do, your code may end up
throwing bad_alloc when the intention was just to throw
bad_lexical_cast, and that can have undesirable consequences for
users.

> The changes required to make the code work under VC have
> made the invisible visible, so the effect is not identical in all
> scenarios.
>
> This leads to a number of possible options:
>
> (1) Use the static solution, as Terje originally intended, and use the
> current solution only for VC6.

-1

> (2) Rollback the design to something closer to the original, ie a fixed-
> string literal message as the result of calling 'what', and provide
> supplementary information for handlers that care enough to catch a
> bad_lexical_cast.

+1

I note that this solution provides a lot more flexibility for someone
who wants to report the error, since

Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-22 Thread David Abrahams
David Abrahams <[EMAIL PROTECTED]> writes:

> Damn, maybe I need to update more/error_handling.html 

Done.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-22 Thread Kevlin Henney
In message <[EMAIL PROTECTED]>, David Abrahams
<[EMAIL PROTECTED]> writes
>
>> I've tried the program below on Intel C++ 7.0 and MSVC 6, and I haven't got
>> it to call terminate(). It may be that it doesn't handle exceptions
>> correctly, though.
>
>Because you are not running in a low-memory condition.

Not quite: there is a difference between the initial construction and
the copy. In an insufficient-memory condition with a compiler that
creates the exception directly, rather than creating and then copying
it, the exception does not become active until the constructor has
completed. If it does not complete, I believe that there is no cause to
call terminate. MSVC is one such compiler, but BCC is not. In an
insufficient-memory condition the former will result in a bad_alloc
being thrown and in the latter a call to terminate.

Given that the workaround in Terje's code was in response to a VC6
limitation (static data members of templates don't initialise
correctly), it may make sense to conditionally compile the code so that
the current code is used for VC6 and Terje's original is used for more
capable compilers.

>>> What's wrong with char const*?
>>
>> You mean storing the string as a character array? 
>
>No, I mean not storing the string at all (char const* is not an
>array), but storing an array is another option.

Storing an array is not a reasonable option in this particular case,
given what the code is trying to achieve. It is either impractical for
the application if the bound is too low or can cause undefined behaviour
if the bound is too high. In other words, unless (or until) the standard
stipulates a limit it's the wrong design whichever way you look at it
for this situation.

>There's no guarantee you have readable names anyway.  

That's a purely theoretical rather than practical consideration. In
practice, I believe that all of the compilers that lexical_cast works
under offer something relatively meaningful. The original version of
lexical_cast simply stated, with a string literal, that the conversion
had failed. There was some user demand for supplementary information,
which Terje's version provided.

However, the decision as to whether this should be in the 'what' string
is perhaps one that can be revisited. It would be feasible to avoid any
allocation issues at all by leaving the human readable string as general
as it was before and adding type_info members that described the source
and target types.

>Finally, you
>should never format exception messages at the throw point.  An
>exception whose what() needs to print type names should store the
>typeids and put the formatting logic in what().

On the whole this is generally good advice, but it should not be treated
as an absolute. Both lazy and eager evaluation have their place in
design. If the effect is the same, it does not matter where the string
is formatted. In this case, Terje's original intent was to use a static
member to hold the representation, which would have resulted in
formatting the string before the constructor, which is the critical
point of failure. The changes required to make the code work under VC
have made the invisible visible, so the effect is not identical in all
scenarios.

This leads to a number of possible options:

(1) Use the static solution, as Terje originally intended, and use the
current solution only for VC6.
(2) Rollback the design to something closer to the original, ie a fixed-
string literal message as the result of calling 'what', and provide
supplementary information for handlers that care enough to catch a
bad_lexical_cast.
(3) Play around with C-style memory management and allocate arrays on
demand, being sure to trap any bad outcome.
(4) Leave as is.

Kevlin


  Kevlin Henney   phone:  +44 117 942 2990
  mailto:[EMAIL PROTECTED] mobile: +44 7801 073 508
  http://www.curbralan.comfax:+44 870 052 2289
  Curbralan: Consultancy + Training + Development + Review

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-22 Thread David Abrahams
Terje Slettebø <[EMAIL PROTECTED]> writes:

>>From: "David Abrahams" <[EMAIL PROTECTED]>
>
>> Terje Slettebø <[EMAIL PROTECTED]> writes:
>>
>> >> C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(74) :
> warning
>> > C4512: 'no_lexical_conversion> > std::char_traits,class std::allocator >,long>' : assignment
>> > operator could not be generated
>> >
>> > This is due to that it stores a const std::string object, describing the
>> > exception
>>
>> Are you saying that you have defined an exception with a std::string
>> member?  That's VERY bad!  Throwing that exception can lead directly
>> to termination!
>
> You mean if the exception itself throws during construction or copying?

Yes.

> I've tried the program below on Intel C++ 7.0 and MSVC 6, and I haven't got
> it to call terminate(). It may be that it doesn't handle exceptions
> correctly, though.

Because you are not running in a low-memory condition.


> As it stands, it prints "Exception - Constructor", as it throws an exception
> in the constructor of the Exception exception. If the throw-statement in the
> constructor is commented out, it prints "Exception - Exception", apparently
> not invoking the copy constructor when throwing the exception (which it's
> allowed to).

Irrelevant.  A program that invokes undefined behavior may appear to
work fine also.

>> What's wrong with char const*?
>
> You mean storing the string as a character array? 

No, I mean not storing the string at all (char const* is not an
array), but storing an array is another option.

> Sure, that's possible, and I see that STLPort do it, and it's
> probably safer, as you say. It does mean you have to specify the
> maximum string length in advance, though. As "no_lexical_conversion"
> what() prints out the source and target types, it may truncate long
> type names.

There's no guarantee you have readable names anyway.  Finally, you
should never format exception messages at the throw point.  An
exception whose what() needs to print type names should store the
typeids and put the formatting logic in what().

Damn, maybe I need to update more/error_handling.html 

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-21 Thread Terje Slettebø
>From: "David Abrahams" <[EMAIL PROTECTED]>

> Terje Slettebø <[EMAIL PROTECTED]> writes:
>
> >> C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(74) :
warning
> > C4512: 'no_lexical_conversion > std::char_traits,class std::allocator >,long>' : assignment
> > operator could not be generated
> >
> > This is due to that it stores a const std::string object, describing the
> > exception
>
> Are you saying that you have defined an exception with a std::string
> member?  That's VERY bad!  Throwing that exception can lead directly
> to termination!

You mean if the exception itself throws during construction or copying?

I've tried the program below on Intel C++ 7.0 and MSVC 6, and I haven't got
it to call terminate(). It may be that it doesn't handle exceptions
correctly, though.

#include 
#include 
#include 

class Exception : public std::runtime_error
{
public:
  Exception() : std::runtime_error("Exception")
{ throw std::runtime_error("Construction"); }

  Exception(const Exception &) : std::runtime_error("Exception (copied)")
{ throw std::runtime_error("Copy"); }
};

int main()
{
  try
  {
throw Exception();
  }
  catch(const std::exception &e)
  {
std::cout << "Exception - " << e.what() << '\n';
  }
  catch(...)
  {
std::cout << "Unknown exception\n";
  }
}

As it stands, it prints "Exception - Constructor", as it throws an exception
in the constructor of the Exception exception. If the throw-statement in the
constructor is commented out, it prints "Exception - Exception", apparently
not invoking the copy constructor when throwing the exception (which it's
allowed to).

> What's wrong with char const*?

You mean storing the string as a character array? Sure, that's possible, and
I see that STLPort do it, and it's probably safer, as you say. It does mean
you have to specify the maximum string length in advance, though. As
"no_lexical_conversion" what() prints out the source and target types, it
may truncate long type names.


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-21 Thread David Abrahams
Terje Slettebø <[EMAIL PROTECTED]> writes:

>> C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(74) : warning
> C4512: 'no_lexical_conversion std::char_traits,class std::allocator >,long>' : assignment
> operator could not be generated
>
> This is due to that it stores a const std::string object, describing the
> exception

Are you saying that you have defined an exception with a std::string
member?  That's VERY bad!  Throwing that exception can lead directly
to termination!

What's wrong with char const*?

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0 (mostlylexical_cast.hpp)

2003-03-21 Thread Terje Slettebø
>From: "John Swartzentruber" <[EMAIL PROTECTED]>

> I downloaded 1.30.0 and tried to build my project. I got a few errors
> that seem to be in boost, primarily in lexical_cast. Also,
> weak_ptr.hpp uses bad_weak_ptr without including
> boost/detail/shared_count.hpp anywhere. I can fix that by
> including it in my code.
>
> These are the warnings in lexical_cast.hpp. Because I treat
> warnings as errors, these pretty much keep me from using this
> version of boost.

In the reported output there are two warnings, both level 4 warnings, which
are more or less remarks. That's why they are disabled in the lexical_cast
unit tests. They are:

> C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(74) : warning
C4512: 'no_lexical_conversion,class std::allocator >,long>' : assignment
operator could not be generated

This is due to that it stores a const std::string object, describing the
exception. "no_lexical_cast" is the concrete exception type returned, and it
inherits from "bad_lexical_cast". The reason it stores a string object,
rather than using a static string member (since the information is the same
for all objects of it), is that MSVC 6 couldn't handle that static
initialisation. Ironic, huh? :)

A simple way to fix this is to make the string object non-const, although
there's really no reason for it to be assigned to, as all objects are the
same.

> C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(147) : warning
C4800: 'void *' : forcing value to bool 'true' or 'false' (performance
warning)
> C:\Program Files\Boost\boost_1_30_0\boost/lexical_cast.hpp(146) :
while compiling class-template member function 'bool __thiscall

This uses the implicit conversion from pointer to bool, and one could
probably avoid the warning with an explicit cast.

An alternative to the above is:

#pragma warning(disable: 4512 4800)

:)


Regards,

Terje

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Re: [boost] MSVC++ 6.0 compiler errors with 1.30.0(mostlylexical_cast.hpp)

2003-03-21 Thread Peter Dimov
John Swartzentruber wrote:
> I downloaded 1.30.0 and tried to build my project. I got a few errors
> that seem to be in boost, primarily in lexical_cast. Also,
> weak_ptr.hpp uses bad_weak_ptr without including
> boost/detail/shared_count.hpp anywhere. I can fix that by
> including it in my code.

weak_ptr.hpp includes shared_ptr.hpp, which in turn includes
detail/shared_count.hpp.

___
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost