Skip to content

Instantly share code, notes, and snippets.

@janwilmans
Created January 30, 2017 20:32
Show Gist options
  • Select an option

  • Save janwilmans/fe0af70d083928f857ffbf138ce0a30d to your computer and use it in GitHub Desktop.

Select an option

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
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();
};
}
@janwilmans
Copy link
Author

The result in case of an exception should be an argument as well, however, that not the point right now :)

@janwilmans
Copy link
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?

@janwilmans
Copy link
Author

janwilmans commented Jan 30, 2017

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?

@StephanTLavavej
Copy link

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