c++templatesc++17template-meta-programminggeneric-lambda

Mutate return type of a lambda


The full context of this problem is unfortunately too involved to explain, but suffice to say it involves some complicated template metaprogramming and I find myself having to do some funny things. I've tried to boil down an issue I've encountered into a minimal example, so the question may seem awkward. If it's possible to do this I'd be interested to know how, if not I'd be interested in hearing possible alternatives.

I'd like to create a function that takes as input a lambda function that may return void or something else. If it does return void, I'd like to convert it into an identical lambda that, instead of returning void, returns true.

template <typename InputFuncType>
auto function_converter(InputFuncType lambda_func)
{
  // I also need to figure out how to deduce the return type of lambda_func
  // might be something like this.
  if constexpr (std::is_same<std::result_of<InputFuncType>::type, void>::value)
  {
    // Current best guess. Note that in the context of the converter, I don't explicitly know
    // lambda_func's input type, so I'm not sure how to do something like this.
    return [](InputFuncType::input_args_t... args) {lambda_func(args); return true;};
  }
  return lambda_func;
}

// target usage
const auto lam1 = [](int a) {return;};
const auto lam2 = function_converter(lam1);

int x = 4;
lam1(x);  // returns void
const bool y2 = lam2(x);  // returns true

I'm using c++17.


Solution

  • A little redundant, I suppose, but the following wrapper should works

    template <typename InputFuncType>
    auto function_converter (InputFuncType lf)
     {
       return [=](auto && ... args)
        {
          using RT = decltype(lf(std::forward<decltype(args)>(args)...));
    
          if constexpr ( true == std::is_same_v<void, RT> )
           {
             lf(std::forward<decltype(args)>(args)...);
    
             return true;
           }
          else
             return lf(std::forward<decltype(args)>(args)...);
        };
     }
    

    Substantially, the idea is transfer the check, about the returned type, inside the internal lambda.