简体   繁体   English

用 arguments 推断 lambda 的返回类型

[英]deduce return type of lambda with arguments

Is it possible to deduce the return type of a lambda function without providing the types of arguments (C++14)?是否可以在不提供 arguments (C++14) 类型的情况下推断出 lambda function 的返回类型? Assume that the return type does not depend on the arguments (ie excluding cases such as f_auto() ).假设返回类型不依赖于 arguments(即不包括f_auto()等情况)。

So far, I have tried to deduce the return type given the types of arguments.到目前为止,我已经尝试根据 arguments 的类型推断返回类型。

// main.cpp

#include <iostream>
#include <type_traits>
#include <typeinfo>
#include <utility>

// Deduces the return type of Func() called with Args, void if invalid.
// Case of no arguments.
template <class Func, class... Args>
class ResultOf {
 private:
  template <class>
  static void Eval(...);
  template <class U>
  static auto Eval(decltype(std::declval<U>()())* r) {
    return *r;
  }

 public:
  using type = decltype(Eval<Func>(0));
};

// Case of one or more arguments.
template <class Func, class T, class... TT>
struct ResultOf<Func, T, TT...> {
 private:
  template <class...>
  static void Eval(...);
  template <class U, class... UU>
  static auto Eval(decltype(std::declval<Func>()( //
      std::declval<U>(), std::declval<UU>()...))* r) {
    return *r;
  }

 public:
  using type = decltype(Eval<T, TT...>(0));
};

template <class... Args, class Func>
std::string GetReturnType(Func func) {
  using type = typename ResultOf<Func, Args...>::type;
  return typeid(type).name();
}

#define P(func, ...)                                                 \
  do {                                                               \
    std::cout << (#func) << '(' << (#__VA_ARGS__) << ')' << "  ->  " \
              << GetReturnType<__VA_ARGS__>(func) << std::endl;      \
  } while (0)

int main() {
  auto f_void = []() { return 0; };
  auto f_int = [](int a) { return a; };
  auto f_int_double = [](int a, double b) { return a + b; };
  auto f_auto = [](auto a) { return a; };

  P(f_void);
  P(f_int, int);
  P(f_int, double);
  P(f_int_double, int, double);
  P(f_int_double, int, int);
  P(f_auto, int);
  P(f_auto, double);
}

Output Output

$ g++ -std=c++14 main.cpp -o main
$ ./main | c++filt -t
f_void()  ->  int
f_int(int)  ->  int
f_int(double)  ->  int
f_int_double(int, double)  ->  double
f_int_double(int, int)  ->  double
f_auto(int)  ->  int
f_auto(double)  ->  double

Update: Solution based on the answer by @igortandetnik更新:基于@igortandetnik 回答的解决方案

// Deduces the return type of `Func::operator() const` if unambiguous.
template <class Func>
class ResultOfDeducedArgs {
 private:
  template <class...>
  static void Eval(...);
  template <class R, class... Args>
  static R Ret(R (Func::*)(Args...) const);
  template <class T>
  static auto Eval(decltype(Ret(&T::operator()))* r) {
    return *r;
  }

 public:
  using type = decltype(Eval<Func>(0));
};

Output Output

f_int()  ->  int
f_int_double()  ->  double
f_auto()  ->  void

If you are willing to limit yourself to non-generic lambdas (and in general to class objects with exactly one operator() overload), then something like this should work (not tested):如果您愿意将自己限制为非泛型 lambda(并且通常仅限于仅具有一个operator()重载的 class 对象),那么这样的事情应该可以工作(未经测试):

template <typename T, typename R, typename... Args>
R ResultOf(R (T::*)(Args...));

Used as用作

using R = decltype(ResultOf(&decltype(my_lambda)::operator()));

This could be wrapped in helper classes for nicer syntax;这可以包装在帮助类中以获得更好的语法; we leave this as an exercise for the reader.我们将此作为练习留给读者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM