2016-12-14 28 views
2

我想重載運營商&&的lambda表達式這需要作爲其輸入任意的(單一)值,併產生一個bool,即是這樣的:超載&&的lambda表達式

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

但是,我不知道我如何定義func_t,以便對應於所需lambda表達式的類型(即,需要任意單個輸入的lambda表達式併產生一個bool

有沒有人知道如何實現這一點?

+1

你不能說出一個lambda的類型,而且每一個都有一個獨特的類型。而且你可能不想重載'&&',因爲你不會得到預期的短路行爲。 – 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 forward將您的lhsrhs轉換爲由operator&&返回的lambda,以避免不必要的副本和支持參考語義。我最近寫了一篇文章:"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

如果拉姆達的參數是已知的,可以使用CAST 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; };