我希望为lambdas重载运算符&&
,该lambdas将任意(单个)值作为输入,并产生bool
,例如:
auto operator&&( func_t lhs, func_t rhs )
{
return []( auto x ){ return lhs(x) && rhs(x) };
}
但是,我不知道如何定义func_t
以便它对应于所需lambda的类型(即,一个lambda采用任意单个输入并产生bool
)
有谁知道如何实施?
答案 0 :(得分:4)
我不确定这是一个好主意,因为正如molbdnilo提到的那样,你不会发生短路,在我看来代码将是误导读者。
无论如何,std::function
是一种代价高昂的抽象,应该避免使用,因为你不需要它的功能。
使用模板功能和std::enable_if
将起作用:
template <typename T>
using returns_bool_when_called_with_int =
std::is_same<decltype(std::declval<T&>()(std::declval<int>())), bool>;
template <typename T0, typename T1>
using lambda_and_enabler = std::enable_if_t
<
returns_bool_when_called_with_int<T0>{} &&
returns_bool_when_called_with_int<T1>{}
>;
template <typename T0, typename T1, typename = lambda_and_enabler<T0, T1>>
auto operator&&( T0 lhs, T1 rhs )
{
// Note that `lhs` and `rhs` are being captured by copy.
// See the note at the end of the post for a more general alternative.
return [=]( auto x ){ return lhs(x) && rhs(x); };
}
上面的代码可以按如下方式使用:
int main()
{
auto l0 = [](int x){ return x % 3 == 0; };
auto l1 = [](int x){ return x % 2 == 0; };
auto l_and = l0 && l1;
assert(l_and(6));
assert(!l_and(5));
assert(!l_and(4));
}
注意:您可能希望将lhs
和rhs
lambdas perfect forward放入operator&&
返回的lambda中,以避免不必要的复制并支持引用语义。我最近写了一篇关于它的文章:"capturing perfectly-forwarded objects in lambdas"。
您的通用operator&&
函数将如下所示:
template <typename T0, typename T1,
typename = lambda_and_enabler<std::decay_t<T0>, std::decay_t<T1>>>
auto operator&&(T0&& lhs, T1&& rhs)
{
return [lhs = FWD_CAPTURE(lhs), rhs = FWD_CAPTURE(rhs)](auto&& x) mutable
{
return access(lhs)(x) && access(rhs)(x);
};
}
答案 1 :(得分:0)
如果已知lambda的参数,则可以使用强制转换为std::function
,如下所示:
std::function<bool (int)> operator &&( std::function<bool (int)> lhs, std::function<bool (int)> rhs )
{
return [&]( int x ){ return lhs(x) && rhs(x); };
}
用法:
auto f = [](int x){ return false; } && [](int x){ return true; };