
At Tue, 12 Oct 2010 15:14:58 -0400, Daniel Walker wrote:
On Tue, Oct 12, 2010 at 2:09 PM, David Abrahams <dave@boostpro.com> wrote:
At Tue, 12 Oct 2010 13:48:37 -0400, Daniel Walker wrote:
Also, swapping out throw_bad_function call does not directly address the boost::function/Boost.Exception coupling issue. If boost::function is going to offer a strong exception safety guarantee, then I believe Boost.Exception is the best way to implement that guarantee, no matter how boost::function gets around to calling boost::throw_exception. (I also think boost::function should continue to offer the strong guarantee.)
Which operation of boost::function are you talking about, that offers the strong guarantee? And how can Boost.Exception be a way to achieve the strong guarantee?
operator() offers a strong guarantee in that it either calls the target or calls boost::throw_exception.
That isn't the strong guarantee; it's just part of the class's non-exceptional semantics. The strong guarantee has to do with what happens *when* an exception is thrown. You should stop using the term that way unless you want to confuse everybody.
I don't mean Boost.Exception is used to "achieve" the guarantee, but to implement it; i.e. in the case where the wrapper is empty, boost::throw_excpetion can be used instead of a throw statement. This is preferable because it allows the exception to be reported with or without RTTI.
Okay.
But some users are asking for a function object wrapper that is not coupled with Boost.Exception.
Why?
Some users who do not use RTTI (e.g. on some embedded system),
I think that's irrelevant. Actually RTTI and EH are orthogonal in principle, though they use similar mechanisms and some compiler vendors may tie them together. In any case Boost.Exception can be configured not to use it.
do not want to take the time to configure Boost.Exception for their platform, and without configuring Boost.Exception, they get unexpected link errors, because boost::throw_exception is undefined.
If users are going to use a subset of C++, they should not be too surprised that they have to add a -D option to their command-line to keep everything linking. Avoiding that is certainly not worth the cost of supporting a parallel copy of boost::function.
boost::function always provides a strong exception safety guarantee. Specifically, if its preconditions are not met, it calls boost::throw_exception.
That's not strong exception-safety. That's throwing an exception where an assert belongs. :-(
I'm using the following definition of strong exception safety.
"The strong guarantee: that the operation has either completed successfully or thrown an exception, leaving the program state exactly as it was before the operation started."
Yes, I invented the term and wrote that definition, but no, you're not using it properly. All constructors with no side-effects offer the strong guarantee, by the way. So asserting that a constructor offers the strong guarantee is not very meaningful once you know that the constructor's semantics are side-effect free.
I suppose there is a nuance here in that the target function could throw, so more formally we could say boost::function has strong exception safety if the target function has strong exception safety.
Sorry, but that makes no sense. Classes don't have strong exception-safety. Only operations do.
Here the definition of the phrase "thrown an exception" depends on the definition of boost::throw_exception, which is user customizable.
I don't think you can redefine the phrase “throws an exception” to mean something that might not throw an exception, and still communicate effectively here.
This is true whether or not the system has RTTI. This is great for some users, but others have asked for a function object wrapper that does not call boost::throw_exception. A simple way to meet this requirement is to provide a function object wrapper that is exception unsafe, like a typical function pointer for example, and that is what unsafe_function does.
IMO a better way to do it would be to make a function object that has no empty state.
I'm amenable to that. What would you call it?
nonempty::function ?
I think if you're looking to supply motivation for unsafe_function, you'll need to describe the goal differently. ;-)
How about this. Typically, function pointers have no RTTI dependency (and no dependency on Boost.Exception) and are exception unsafe.
In what sense are function pointers exception-unsafe?!
Their behavior is undefined when they are null; i.e. when they are invoked they offer neither a basic, strong nor nothrow guarantee.
That is *not* exception-unsafe! There are documented preconditions on the function call operator, and you must satisfy them or all bets are off. Almost every operation in std:: has such conditions here or there. That doesn't make them exception-unsafe. Exception-unsafe means that *when* an exception is thrown, invariants are violated (or resources leaked).
unsafe_function is a function object wrapper that behaves more like a function pointer with respect to exception safety.
I am beginning to think you have a different definition of exception safety from the rest of the world.
Well, it's important to use similar definitions. I'm trying to stick to the definition above. How can I do this better?
Other than studying the definitions and taking them literally, I don't know what to suggest. -- Dave Abrahams BoostPro Computing http://www.boostpro.com