
On Mon, Oct 11, 2010 at 4:13 PM, Emil Dotchevski <emil@revergestudios.com> wrote:
On Mon, Oct 11, 2010 at 12:57 PM, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On Mon, Oct 11, 2010 at 3:20 PM, Emil Dotchevski <emil@revergestudios.com> wrote:
On Mon, Oct 11, 2010 at 11:53 AM, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On Mon, Oct 11, 2010 at 2:45 PM, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On Mon, Oct 11, 2010 at 2:05 PM, Emil Dotchevski <emil@revergestudios.com> wrote:
On Mon, Oct 11, 2010 at 10:45 AM, Daniel Walker <daniel.j.walker@gmail.com> wrote: > On Mon, Oct 11, 2010 at 2:49 AM, Nevin Liber <nevin@eviloverlord.com> wrote: >> On 11 October 2010 00:01, Emil Dotchevski <emil@revergestudios.com> wrote: >>> On Sat, Oct 9, 2010 at 12:38 PM, Daniel Walker >>> <daniel.j.walker@gmail.com> wrote: >>>> Finally, there have been suggestions to alter boost::function's >>>> exception safety guarantee directly through either policies or >>>> constructor options. >>> >>> We used to have an Allocator parameter to the boost::function template >>> and it was removed (just in time for this change to also be reflected >>> in C++0x) to reduce coupling. >> >> So what exactly is the proposed behavior if the function object cannot >> fit in the small object optimization space of unsafe_function and the >> allocation fails? > > As proposed, unsafe_function has the same semantics as boost::function > with one (and only one) exception: the behavior of operator() is > undefined when it has no target.
If that was the only motivation, you could just disable exception handling, and then define:
namespace boost { void throw_exception( std::exception const & ) { assert(0); } }
Correct. But users have complained about this, which is exactly the motivation for unsafe_function. It works out-of-the-box in RTTI-free environments with no dependency on boost::throw_exception. It's a simple problem really.
P.S. Sorry I spoke to soon. That's not exactly correct. A user could do what you describe, but boost::function could not, since that would change its exception safety guarantee; i.e. it would no longer throw (or call a user definable function) when it had no target.
This is not exception safety issue, it is a choice between defined and undefined behavior.
A strong exception safety guarantee is a defined behavior.
Any behavior fits "undefined behavior". Like I said, if someone wants undefined behavior, they can't be against any particular behavior, including throwing an exception.
Another group of users, would like a function wrapper without coupling Boost.Exception, and indeed, without an exception safety guarantee. unsafe_function address the demands of this second group of users.
What is the problem with adding a constructor such that you could say:
boost::function<T>(f,std::nothrow)
This way, I'm pretty sure that as long a program only instantiates the nothrow constructors, the resulting executable won't depend on boost::throw_exception.
True, that can be done, but boost::function is still default constructible and can still be cleared through assigning 0. So, you end up back to the exception safety question of how operator() behaves when the wrapper is empty. As you suggest, you could have the behavior depend on how it was constructed, so sometimes boost::function has a strong exception guarantee, sometimes it has a nothrow guarantee (and presumably, it's a no-op when empty). This is a matter of personal preference. To me it's simpler to say that boost::function always has a strong exception safety guarantee, as is currently the case, and other function object wrappers could be added to offer other guarantees, including no guarantee, like a plain vanilla function pointer, which is what unsafe_function does. Under this scheme, we could also add nothrow_function that would offer a nothrow guarantee, and semantically, it would be a no-op when empty, per your example. Daniel Walker