提问人:francesco 提问时间:11/7/2023 更新时间:11/7/2023 访问量:88
确定具有不同签名的 lambda 的结果类型
determine result type of lambdas with different signature
问:
假设我有一个例程,它接收一个可调用的 Lambda 作为参数,并且允许这个 Lambda 有 2 个签名:它可以称为提供 int 或 2 ints。
问题是:如何确定此 Lambda 的结果类型。
下面的代码说明了该问题
#include <iostream>
#include <type_traits>
template <class Lambda>
auto f(Lambda&& f)
{
using result_type = std::conditional_t<std::is_invocable_v<Lambda, int>, std::invoke_result_t<Lambda, int>, std::invoke_result_t<Lambda, int, int>>;
result_type res;
if constexpr (std::is_invocable_v<Lambda, int>) {
res = f(3);
}
else {
res = f(3, 3);
}
return res;
}
int main()
{
std::cout << f([](int x) -> int { return x; }) << std::endl;
std::cout << f([](int x, int y) -> int { return x * y; }) << std::endl;
return 0;
}
在 Coliru 上实时检查。
代码不编译,因为在里面,必须定义第二个和第三个模板参数,而这里显然只有一个。std::conditional_t
我可以考虑编写一个用于解决这个问题的特征,比如利用模板专业化。类似的东西
template <class F, bool T>
struct helper;
template <class F>
struct helper<F, true> {
using type = std::invoke_result_t<F, int>;
};
template <class F>
struct helper<F, false> {
using type = std::invoke_result_t<F, int, int>;
};
但在重新发明轮子之前:有没有使用 std 库的更简单的紧凑解决方案?我对 c++17 解决方案感兴趣。
答:
3赞
Ted Lyngmo
11/7/2023
#1
我不确定这是否比你自己的类型特征有任何好处。它只是不同,它不允许歧义(当两个重载同样合适时),这可能是不需要的:
template<class L> auto foo(L&&) -> std::invoke_result_t<L, int>;
template<class L> auto foo(L&&) -> std::invoke_result_t<L, int, int>;
template <class Lambda>
auto f(Lambda&& f) {
using result_type = decltype(foo(std::forward<Lambda>(f)));
// ...
}
std::invoke_result::type
- 如果使用参数调用,则 Callable 类型的返回类型。仅当可以在未计算的上下文中使用参数调用时才定义。F
ArgTypes...
F
ArgTypes...
或者使用你已经拥有的东西并直接初始化:res
template <class Lambda>
auto f(Lambda&& f) {
decltype(auto) res = [&] {
if constexpr (std::is_invocable_v<Lambda, int>) {
return f(3);
} else {
return f(3, 3);
}
}();
// do other stuff ...
return res;
}
1赞
463035818_is_not_an_ai
11/7/2023
#2
在您的示例中,您不需要 ,但这将执行以下操作:result_type
template <class Lambda>
auto f(Lambda&& f)
{
if constexpr (std::is_invocable_v<Lambda, int>) {
return f(3);
}
else {
return f(3, 3);
}
}
如果你在实际代码中确实需要,可以通过 或 从上面删除它。result_type
f
decltype(f(the_lambda))
std::invoke_result_t<f,Lambda>
2赞
Jarod42
11/7/2023
#3
从你的代码中,你只需要“延迟”评估:
using result_type =
std::conditional_t<std::is_invocable_v<Lambda, int>,
std::invoke_result<Lambda, int>,
std::invoke_result<Lambda, int, int>>::type;
上一个:C++ 模板化 - 可选构造函数
评论
std::conditional
if constexpr
result_type