Boost logo

Boost :

From: William E. Kempf (wekempf_at_[hidden])
Date: 2002-11-20 18:38:15

David Abrahams said:
> "William E. Kempf" <wekempf_at_[hidden]> writes:
>>> There are workarounds for that problem. See
>> Thanks for the link. Comments:
>> * I personally don't agree with the rationale that not throwing
>> bad_alloc when constructing from a string is not necessarily a bad
>> thing. As bad as exception specifications are, they are at least
>> useful as documentation
> Not very. Don't forget that derived classes pass.

*being dumb* What do you mean by that last sentence?

>> and this automatically adds another exception type to the list that
>> may not have otherwise been there.
> Not unless your compiler is broken. Exception specifications are
> strictly enforced at runtime.

I was referring to specification as documentation, not as an actual
specification in the code. For instance, the boost::thread_lock_error is
specified to be thrown in the documentation of several Boost.Threads
methods, but what's not documented (which means a bug either in the
documentation or the implementation, but that answer is unsatisfying) is
that this means std::bad_alloc may also be thrown.

But, frankly, the using specification in the actual code would make this
point even stronger, as this may mean a call to unexpected() instead.

>> * It's nice to know that the copy constructor is technically not
>> allowed to throw, but how many implementations get this wrong today?
> None, to my knowledge.

Surprising, but if true, reassuring.

>> At the very least, it would be nice if we had a boost::exception
>> (derived from std::exception) as a base, which included the const
>> char* constructor to eliminate the problem with the string
>> constructor,
> There is no problem with the string constructor, because that
> constructor doesn't exist in std::exception.

No, but it does in the branches for logic_error and runtime_error. The
logic is that if all of our exceptions are based of off boost::exception,
we can avoid the issue found in those branches. (OK, this isn't an
argument for having our own exceptions, exactly, but I wasn't trying to
make that argument.)

>> and that ensured nothrow copies.
> You can't ensure that in a base class. A derived class can always
> throw in its copy-ctor.

Yeah, but that wasn't the point I was trying to make. I simply meant that
IIF we do have a Boost exception heirarchy, it shouldn't force the issue
of dynamic allocation of strings on the user at any node of the tree.

>>>> and the string isn't language neutral.
>>> Neither is your source code. You don't need to use the string for
>>> language-neutral messages.
>> No, but it is desirable to provide language neutral strings
> What's a language-neutral string? "42"?

A string that's based on the users locale.

>> that describe what exception was thrown, and possibly why and/or from
>> where, etc. This isn't to say that what() is bad because it's not
>> language neutral
> ?? It's as language-neutral as you make it. It's just a string.
>> only that there's (at least in some circumstances) a desire for a
>> language neutral description of what went wrong.
> Localization should not the be the job of an exception class.

This shows that you did understand what I was trying to convey, despite
the numerous questions that do nothing but point out how badly I described
the problem ;).

I don't expect the exception to provide localization, only that it provide
the necessary hooks for localization to be easily implemented.

>>>> I'd prefer a what() that returned a key which never had to be
>>>> allocated
>>> It does; you can always return a string literal.
>> Uhm... yes, so long as you can supply that key with out having to use
>> the string constructors from most of the standard exceptions.
> ?? Aren't we talking about whether a boost::exception is needed?
> Wouldn't that just be derived from std::exception? What's the
> problem?

If you leave it just at the root of the tree, nothing. I just expected
we'd have the logic_error and runtime_error branches as well... but that
may have been a bad expectation.

>>>> and possibly could be used to index into a catalog of language
>>>> neutral strings for output.
>>> Existing what() does that.
>> How so? I can think of a few hacks, but none seem completely
>> satisfying.
> std::map<char const*, std::string, compare_cstring>?

This assumes that the what() strings are all unique, gives suboptimal
performance in lookups, and doesn't allow for specifying data to be
formatted into the string. But at this point I think I can safely assume
you don't care about these points, which is a valid point of view.

>> std::exception is nearly the perfect design (it's the logic_error and
>> runtime_error branches in the heirarchy I have problems with, though
>> as you pointed out there are ways to fix those). The only problem is
>> how you allow the strings to be made language neutral. From what you
>> said above, I assume you think there's a solution to that, but I don't
>> see it. Care to point out what I'm not seeing?
> If there's an answer, it's in a different domain. I don't think that
> belongs in an exception class.

Yes, and no. The actual act of retrieving a localized string obviously
doesn't belong in this domain. However, providing a key for looking up
said strings, and a hook for formatting said strings with instance
specific data, would sure be nice IMHO.

// hypothetical code...
catch (const boost::exception& e)
   std::string str = lookup(e.key());
   // 'str' no contains a locale specific string with replacable value
   // markers, for instance:
   // "bad_argument '${argument}' thrown in ${function}"
   std::cout << e.format(str) << std::endl;
   // given the above hypothetical locale specific string we might get:
   // bad_argument 'first_arg' thrown in some_class::foo

Obviously a toy example, but I think this illustrates the idea.

William E. Kempf

Boost list run by bdawes at, gregod at, cpdaniel at, john at