Ich bin nicht sicher, das eine gute Idee ist, weil, als molbdnilo erwähnt, werden Sie nicht kurzschließen und meiner Meinung nach wird der Code für die Leser irreführend sein.
Wie auch immer, std::function
ist eine kostspielige Abstraktion und sollte hier vermieden werden, da Sie seine Funktionen nicht benötigen.
eine Template-Funktion und std::enable_if
wird Verwenden arbeiten:
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); };
}
Der obige Code wie folgt verwendet werden:
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
Hinweis: möchten Sie perfect forward Ihre lhs
und rhs
Lambdas in das Lambda von operator&&
zurückgegeben, um unnötige Kopien zu vermeiden und Referenzsemantik zu unterstützen. Ich habe kürzlich einen Artikel dazu geschrieben: "capturing perfectly-forwarded objects in lambdas".
Ihre allgemeine operator&&
Funktion würde dann wie folgt aussehen:
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);
};
}
Sie nicht den Typ eines Lambda nennen kann, und jeder hat eine einzigartige Art. Und Sie wollen wahrscheinlich nicht "&&" überladen, da Sie das erwartete Kurzschlussverhalten nicht bekommen werden. – molbdnilo