【发布时间】:2020-11-05 14:53:12
【问题描述】:
是否可以在不提供参数类型的情况下推断 lambda 函数的返回类型(C++14)?
假设返回类型不依赖于参数
(即排除f_auto()等情况)。
到目前为止,我已经尝试根据参数类型推断返回类型。
// 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);
}
输出
$ 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
更新:基于@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));
};
输出
f_int() -> int
f_int_double() -> double
f_auto() -> void
【问题讨论】:
-
f_auto是多态恒等函数,可以称为f_ident;顺便说一句,f_auto(f_auto)的类型呢?另见type inferencewikipage -
你用这个做什么?当然只是明确地写出返回类型应该可以工作....
-
@Evg 这需要 C++17
-
@CoffeeTableEspresso 我需要将此 lambda 传递给模板函数,其逻辑取决于返回类型