[英]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.