Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enforce "noexcept" on std::function?

This code compiles and runs, throwing the int:

#include <functional>

void r( std::function<void() noexcept> f ) { f(); }

void foo() { throw 1; }

int main()
{
    r(foo);
}

However I would like the compiler to reject the line r(foo); because r should only be passed a noexcept function. The noexcept specifier appears to be ignored. Is there any way to achieve that?

Edit: This question is different to Is knowledge about noexcept-ness supposed to be forwarded when passing around a function pointer? because I am asking for a remedy, specifically in the case of std::function.

like image 696
M.M Avatar asked Jul 24 '15 05:07

M.M


People also ask

What happens when Noexcept function throws?

noexcept means that a function will not throw, not that it cannot throw, and the penalty for failure to comply is calling std::terminate , not UB.

What is Noexcept specifier in C++?

noexcept specifier(C++11) noexcept operator(C++11) Dynamic exception specification(until C++17) [edit] Specifies whether a function could throw exceptions.


1 Answers

I've also stumbled across this problem. My solution was to use a delegating object (delegating to the std::function). The delegate has a no-except specification. It could still be improved (move added, etc.).

Here it goes:

#include <functional>

template <class FuncT>
struct NoExceptDelegate;

template <class R, class ... Args >
struct NoExceptDelegate<R(Args...)>
{
    NoExceptDelegate(std::function<R(Args...)>&& callback)
      : callback_(move(callback))
    {
        if (!callback_)
        {
            throw std::invalid_argument( "NoExceptDelegate requires a valid callback");
        }
    }

    template <class...ArgsU>
    R operator()(ArgsU&&... args) noexcept
    {
        return callback_(std::forward<ArgsU>(args)...);
    }

  private:
      std::function<R(Args...)> callback_;
};

This is typically used as a contract in an asynchronous interface to indicate that the provided handler shall not throw e.g.:

struct Interface
{
    virtual void doSomethingAsynchronous(
        NoExceptDelegate<void(int)> onCompletionResult) = 0;
    //...etc
};

As the client is the callback provider, NoExceptDelegate is a promise from the provider that provided shall not fail. The provider should ensure that at least std::function provided is callable.

like image 94
Werner Erasmus Avatar answered Oct 25 '22 04:10

Werner Erasmus