Я не уверен, что это хорошая идея, потому что, как указано 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));
}
wandbox example
Примечание: вы можете захотеть perfect forwardlhs
и rhs
lambdas в лямбда, возвращенный operator&&
, во избежание ненужных копий и поддержки эталонная семантика. Недавно я написал статью об этом: "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);
};
}
Вы не можете назвать тип лямбды, и каждый из них имеет уникальный тип. И вы, вероятно, не хотите перегружать '&&', так как вы не получите ожидаемого короткого замыкания. – molbdnilo