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
.
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.
noexcept specifier(C++11) noexcept operator(C++11) Dynamic exception specification(until C++17) [edit] Specifies whether a function could throw exceptions.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With