Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

User-defined deduction guide for lambda

today I'm struggling with C++ templates. This is my simple code for convenient exception handling in JNI code.

template<typename T>
std::optional<T> handleNativeCrash(JNIEnv *env, std::function<T(void)> f) {
    try {
        return std::optional<T>(f());
    }
    catch (const std::exception &e) {
        jniThrowException(env, e.what());
        return {};
    }
}

When I try to use it without specifying T, Clang fails roughly with this error

no matching function for call to 'handleNativeCrash'
      return my_namespace::handleNativeCrash(env, [&]{
             ^~~~~~~~~~~~~~~~~~~~~
  /......../jni.cpp:116:39)'
      std::optional<T> handleNativeCrash(JNIEnv *env, std::function<T(void)> f) {
                       ^
  1 error generated.

I would like to infer T automatically from lambda return type. I tried to write deduction guide, but it seems that I'm unable to write it for global function. I tried to create simple template struct which contained only this function, but I failed too. It seems I don't really understand C++ template metaprogramming.

My first attempt was like this, but Clang just crashed complaining about illegal syntax and printing it's backtrace. I will report bug soon, but I need to finish this job first.

template<typename T>
handleNativeCrash(JNIEnv *env, std::function<T(void)> f) -> handleNativeCrash<decltype(f())>;

How can I achieve my goal?

like image 443
Inline Avatar asked Oct 18 '25 07:10

Inline


1 Answers

You cannot use template deduction for that, it's not smart enough and only works on matching.

But you can manually infer it:

template<class Callable>
auto handleNativeCrash(JNIEnv *env, Callable f)
-> std::optional<decltype(f())>
{
    try {
        return f();
    }
    catch (const std::exception &e) {
        jniThrowException(env, e.what());
        return {};
    }
}

Simplified live demo

like image 124
YSC Avatar answered Oct 20 '25 21:10

YSC