
On Tue, Oct 12, 2010 at 4:15 PM, David Abrahams <dave@boostpro.com> wrote:
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:
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.
Sorry, I may not have been clear. In order to configure Boost.Function to work without RTTI, you need to define a function not a configuration macro. So, there is no -D option. This is part of the reason that some users are frustrated.
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.
OK, thanks for the help. Sorry for the confusion.
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'm only talking about operator(), so I should have said boost::function invocation has strong exception safety, instead of just "boost::function has strong exception safety," which was incorrect usage.
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.
Right, so I'll rephrase. Formally, boost::function invocation has strong exception safety if invoking the target function has strong exception safety.
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.
Yes, this could be confusing. For this to be meaningful you would have to be clear about using boost::throw_exception instead of a throw statement and the reader would need to be familiar with Boost.Exception. But I don't think that's too much to ask.
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 ?
OK, I might try to roll this together. It could be a better solution.
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).
OK. I think I see the confusion here. I was using the exception safety guarantees to describe how an operation behaves when its preconditions are not met, but you use the terms only to describe how an operation behaves when an exception is thrown. With boost::function these are the same events; it throws an exception when its preconditions aren't met. With a function pointer, the system checks the preconditions and may throw an exception or terminate execution with a segfault or whatever. I was trying to make an analogy between invoking an empty function object wrapper and invoking a null function pointer. Anyway, to avoid confusion, I'll stop using this analogy, and I will not use the exception safety guarantees to refer to the behavior of a function pointer invocation.
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.
Thanks. I will try to do so. Daniel Walker