2017-01-23 22 views
0

一元和二元否定器的用處很容易理解。如何編寫n-ary否定符?

與一元否定符(NOT1)實施例:

class Even 
{ 
public: 
    bool operator() (const int& x) const { return x % 2 == 0; } 
    typedef int argument_type; 
}; 

int values[] = { 9, 1, 8, 2, 7, 3, 6, 4, 5 }; 

int even = count_if(values, values + 9, Even()); 
int odd = count_if(values, values + 9, not1(Even())); // <= unary negator 
cout << "We have " << even << " even elements in the array.\n"; 
cout << "We have " << odd << " odd elements in the array.\n"; 

輸出:

We have 4 even elements in the array. 
We have 5 odd elements in the array. 

實施例具有二進制否定符(NOT2):

int values[] = { 9, 1, 8, 2, 7, 3, 6, 4, 5 }; 

// original array 
for (int i : values) 
    cout << i << " "; 
cout << "\n"; 


// array in ascending order 
sort(values, values + 9, less<int>()); 

for (int i : values) 
    cout << i << " "; 
cout << "\n"; 

// array in descending order 
sort(values, values + 9, not2(less<int>())); // <= binary negator 

for (int i : values) 
    cout << i << " "; 
cout << "\n\n"; 

輸出:

9 1 8 2 7 3 6 4 5 
1 2 3 4 5 6 7 8 9 
9 8 7 6 5 4 3 2 1 

什麼n元非門(NOT3,not4,NOT5 ... notn)?

讓我們假設我需要計算之間的元素數量,而不是之間的兩個數字(下限和上限)集合(可能是一個數組)。

. 

int elems_betweem = count_if(values, values + n, not3(bind(Between<int>(), _1, lowerValue, upperValue))); 

. 

我如何寫NOT3否定器?

更有甚者,我們是否有一個通用的not作爲not1not2以同樣的方式爲bind VS bind1stbind2nd一個替代品?

謝謝

+2

這裏你不需要'not3' - bind(在(),_1,lowerValue,upperValue)之間''會創建一個一元運算符,所以你只需要一個'not1'。 – Holt

+1

C++ 17被提議引入:'std :: not_fn',它可以用於任何arity。 – user2079303

+0

在你的例子中,你將需要'not1'而不是'not3'。 'bind(在(),_1,lowerValue,upperValue)之間的返回值'是一個可調用的參數,而不是3. –

回答

1

由於C++ 17 std::not_fn將可用:

auto between = [](int value, int lowerValue, int upperValue) { 
    return lowerValue < value && value < upperValue; 
}; 

int elems_between = std::count_if(std::cbegin(values), std::cend(values), 
    std::bind(std::not_fn(between), std::placeholders::_1, lowerValue, upperValue)); 

wandbox example

+0

BRILLIANT !!!你回答這個問題,並且在未來版本的C++中編寫一個工作示例。我每天都越來越喜歡C++!上帝該死的.NET和Java! – user7140484

0

我如何寫NOT3否定器?

A C++ 03兼容的例子:

template<class Pred> 
class ternary_predicate { 
    Pred pred; 
public: 
    ternary_predicate(Pred pred): pred(pred){} 

    template<class A, class B, class C> 
    bool 
    operator()(A const& a, B const& b, C const& c) const { 
     return !pred(a, b, c); 
    } 
}; 

template<class Pred> 
ternary_predicate<Pred> 
not3(Pred pred) { 
    return ternary_predicate<Pred>(pred); 
} 

更有甚者,我們有一個通用的不是NOT1和NOT2的替代品以同樣的方式作爲約束VS bind1st和bind2nd?

我們將一旦C++ 17正式發佈。建議引入std::not_fn作爲std::not1std::not2的替代品,然後將被棄用。

如果你覺得不耐煩,它不應該是很難實現自己在C++ 14:

template<class Pred> 
auto 
not_fn(Pred&& pred) { 
    return [pred=std::forward<Pred>(pred)](auto&&... args){ 
     return !pred(std::forward<decltype(args)>(args)...); 
    }; 
} 
0

您可以編寫自己的std::not_fn,只要它是不可用:

template <typename T> 
struct not_func 
{ 
    template <typename...Args> 
    constexpr bool operator()(const Args&...args) const { return !T{}(args...); } 
}; 

實例:

int main() 
{ 

    bool a1 = std::less<int>{}(1, 2); 
    bool a2 = not_func<std::less<int>>{}(1, 2); 

    bool b1 = Even{}(1); 
    bool b2 = not_func<Even>{}(1); 


    std::cout 
     << "a1 = " << (a1 ? "true" : "false") << "\n" 
     << "a2 = " << (a2 ? "true" : "false") << "\n" 
     << "b1 = " << (b1 ? "true" : "false") << "\n" 
     << "b2 = " << (b2 ? "true" : "false") << "\n"; 
} 

[On Coliru] [On Godbolt]

我還沒有測試所有可能的變體,所以這可能仍然是越野車。