'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.



Solution 1:[1]

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);

Solution 2:[2]

I think it is not possible to enforce that at compile time. In the same way that the compiler does not ensure that bare throw (rethrow) must be called inside a catch-block.

(Note that in the Lippincott function throw is inside a try-block not a catch-block.)

However static analysis tools like cppcheck 2.5 or maybe clang-tidy can detect these uses of bare throw outside catch, so they might be able to also detect misuses of lippincott().

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 alfC