2016-12-14 2 views
2

Я хочу, чтобы перегрузить оператор && для лямбды, который принимает в качестве ввода произвольной (один) значение и дает bool, то есть, что-то вроде:перегрузки && для лямбды

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

Однако, я понятия не имею, как я должен определить func_t, так что это соответствует типу желаемых лямбда (то есть, лямбда, которая принимает произвольный один вход и дает bool)

Кто-нибудь знает, как это можно реализовать?

+1

Вы не можете назвать тип лямбды, и каждый из них имеет уникальный тип. И вы, вероятно, не хотите перегружать '&&', так как вы не получите ожидаемого короткого замыкания. – molbdnilo

ответ

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

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

Если аргументы лямбда известны, вы можете использовать приведение к 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; }; 
Смежные вопросы