Created
January 30, 2017 20:32
-
-
Save janwilmans/fe0af70d083928f857ffbf138ce0a30d to your computer and use it in GitHub Desktop.
Pack exceptions to pass them though a layer that does not support exceptions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| template<typename Result, typename ...Args> | |
| auto dzn_callee_2(std::function<Result(Args...)> fn) -> std::function<Result(std::exception_ptr context, Args...)> | |
| { | |
| return [=] (std::exception_ptr context, Args&&... args) mutable -> Result | |
| { | |
| try | |
| { | |
| return fn(std::forward<Args>(args)...); | |
| } | |
| catch (const std::exception&) | |
| { | |
| context = std::current_exception(); | |
| } | |
| return Result(); | |
| }; | |
| } |
Author
Author
calling it like:
auto f = dzn_callee_2(std::function<int(int)> ([&] (int a) { return mightThrow(a); }));
works, but I don't like to repeat myself, and would to call it like:
auto f = dzn_callee_2(([&] (int a) { return mightThrow(a); });
it doesn't seem possible?
Author
So I wrote:
template<typename Object, typename Result, typename ...Args>
auto dzn_callee(Object &object, Result (Object::*fn)(Args...)) -> std::function<Result(std::exception_ptr, Args...)>
{
return [=] (std::exception_ptr context, Args&&... args) mutable -> Result
{
try
{
return (object.*fn)(std::forward<Args>(args)...);
}
catch (const std::exception&)
{
context = std::current_exception();
}
return Result();
};
}
but, it's kinda ugly... and not as generic as it might be, can we do better?
Here is my suggestion:
C:\Temp>type meow.cpp
#include <exception>
#include <utility>
template <typename F> auto wrap(F&& f) {
return [g = std::forward<F>(f)](std::exception_ptr& context, auto&&... args) mutable {
try {
return g(std::forward<decltype(args)>(args)...);
} catch (...) {
context = std::current_exception();
return decltype(g(std::forward<decltype(args)>(args)...)){};
}
};
}
#include <iostream>
#include <stdexcept>
#include <string>
using namespace std::string_literals;
int main() {
std::exception_ptr ep;
std::cout << std::boolalpha;
std::cout << wrap(std::plus<>{})(ep, "Hello"s, "Kitty") << "\n";
std::cout << !!ep << "\n";
std::cout << wrap([](int) -> int { throw std::runtime_error("oops"); })(ep, 2017) << "\n";
std::cout << !!ep << "\n";
}
C:\Temp>cl /EHsc /nologo /W4 /MTd meow.cpp
meow.cpp
C:\Temp>meow
HelloKitty
false
0
true
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The result in case of an exception should be an argument as well, however, that not the point right now :)