2016-12-14 1 views
2

ich den Betreibers && für Lambda-Ausdrücke, um eine Überlastung will, das einen beliebigen (single) Wert als Eingabe verwendet und ergeben ein bool, das heißt, so etwas wie:Überlastung && für lambdas

auto operator&&(func_t lhs, func_t rhs) 
{ 
    return [](auto x){ return lhs(x) && rhs(x) }; 
} 

Allerdings habe ich keine Ahnung, wie muss ich func_t so definieren, das entspricht dem Typ des gewünschten Lambdas (dh ein Lambda, das einen beliebigen Einzeleingang nimmt und bool ergibt)

Hat jemand eine Idee wie dies umgesetzt werden kann?

+1

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

Antwort

4

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); 
    }; 
} 
0

Wenn die Argumente von Lambda bekannt sind, können Sie cast std::function wie folgt verwenden:

std::function<bool (int)> operator &&(std::function<bool (int)> lhs, std::function<bool (int)> rhs) 
{ 
    return [&](int x){ return lhs(x) && rhs(x); }; 
} 

Verbrauch:

auto f = [](int x){ return false; } && [](int x){ return true; };