Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a "safe" way to declare a lippincott function so that it won't be called outside of a catch?

A Lippincott function is a function which converts an exception into a return code that can be safely handled in a callback from another language which did not support exceptions, such as C. Such functions, because they deliberately use throw with no argument, thereby rethrowing the most recently caught exception, cannot be called outside the context of a catch block.

I am wondering if modern C++ (c++17 or c++20) has any declaration mechanism for specifically identifying such functions, and ensuring that a function is only ever called from the context of a catch block (or from the context of another such function), generating a compile time error if it is called from any other context.

like image 929
markt1964 Avatar asked Mar 12 '19 21:03

markt1964


2 Answers

There is no way to tell the compiler that a particular function should only be called from a catch handler.

You can, however, call std::current_exception() from within your Lippincott function to determine if there currently an exception being handled. If this returns a nullptr then there is no exception active. You can then handle this at runtime by triggering an assert and/or having your function return (and not use throw).

like image 117
1201ProgramAlarm Avatar answered Nov 19 '22 02:11

1201ProgramAlarm


There is no compile time syntax to inform that a function must only be called when there exists a current exception. It can only be detected at runtime, whether such current exception does exist.

You could use higher-order programming, and instead of providing the lippincott function, provide a wrapper which does the entire try-call-catch-lippincott for a given function:

auto with_catch = [](auto&& f, auto&& c, auto&&... args) -> decltype(c()) {
    try {
        f(std::forward<decltype(args)>(args)...);
        return {};
    } catch (...) {
        return c();
    }
};

auto with_lippincott = [](auto&& f, auto&&... args) {
    return with_catch(
        std::forward<decltype(f)>(f),
        lippincott,
        std::forward<decltype(args)>(args)...
    );
};

This is not so easy to misuse. Usage example:

foo_Result r3 = with_lippincott(Snafuscate, true);
like image 38
eerorika Avatar answered Nov 19 '22 02:11

eerorika