Es gibt mehrere verwandte Fragen, z.B. algorithms with multiple (unary) predicates oder multiple predicates in general. Aber sie scheinen den generischen Fall, den ich anstrebe, nicht anzugehen, und die Antworten sind oft veraltet, weil sie sich auf Konstrukte beziehen, die in C++ 11 veraltet sind. Es könnte alles auf herunterkochen, aber ich bin mir nicht sicher, ob es als ein Duplikat betrachtet werden kann.Wie erstellt man eine generische Funktion für die Kombination von binären Prädikaten?
Ich habe versucht, eine Funktion zu erstellen, die zwei beliebige binäre Prädikate (im Sinne von „Typen, die ein Zwei-Argument operator()
und gibt ein bool
implementieren“) kombiniert. Mein Ziel war es, die Möglichkeit zu haben, Code wie folgt zu schreiben:
auto p0 = somePredicate();
auto p1 = someOtherPredicate();
auto p2 = evenMorePredicates();
auto combined = and(p0, or(p1, p2));
Ich weiß, dass etwas Ähnliches kann mit lambdas erreicht werden (wie auch in der Antwort auf eine der Fragen oben verlinkten vorgeschlagen), aber dies erfordert die Argumenttypen, die im Lambda selbst wiederholt werden sollen. Ich würde gerne wissen, wie eine solche and
oder or
Funktion wirklich implementiert werden könnte generisch - insbesondere für binäre Prädikate mit beliebigen Argumenttypen.
Mein grundlegender Ansatz (und ein eindruck Beispiel) ist der folgende:
#include <functional>
#include <iostream>
template <typename A, typename B, typename P0, typename P1>
std::function<bool(const A&, const B&)> and(
const P0& p0, const P1& p1)
{
return [p0, p1](const A& a, const B& b)
{
return p0(a, b) && p1(a, b);
};
}
int main(int argc, char* argv[])
{
auto p0 = [](const int& a, const int& b)
{
return a < 0 && b > 0;
};
auto p1 = [](const int& a, const int& b)
{
return a < 1 && b > 4;
};
// This is what I want:
//auto combined = and(p0, p1);
// This works, but ...
auto combined = and<int, int, std::function<bool(const int&, const int&)>, std::function<bool(const int&, const int&)>>(p0, p1);
std::cout << "combined(-3,7) : " << combined(-3, 7) << std::endl;
std::cout << "combined(-3,1) : " << combined(-3, 1) << std::endl;
return 0;
}
In jedem Fall ist das Problem, dass die Template-Parameter der Argumenttypen zu sein scheint, können nicht an der Aufrufstelle abgeleitet werden. Ich habe versucht, Variationen davon, basierend auf anderen verwandten Fragen hier auf Stackoverflow, aber ohne Erfolg. Mein Bauchgefühl ist, dass es dafür eine (einfache) Lösung geben muss, die einige Einschränkungen des Typ-Deduktionssystems von Lambda umgeht, aber ich habe offensichtlich noch nicht den richtigen Weg gefunden.
Sie könnten einfach 'pred_and (p0, p1)'. Beachten Sie, dass 'und' ein reserviertes Wort ist. –
TartanLlama
Das Ableiten der Parametertypen für den zurückgegebenen Abschluss ist im generischen Fall nicht wirklich möglich. Was, wenn Ihr Prädikat ein generisches Lambda oder eine Funktion mit mehreren 'operator()' Überladungen ist? – TartanLlama
können Sie [C++ 14] (http://coliru.stacked-crooked.com/a/d9329a693b80f4ed) verwenden? –