Search code examples
c++functoradaptor

How to write a n-ary negator?


The usefulness of unary and binary negators is easily understandable.

Example with unary negator (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";

Output:

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

Example with binary negator (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";

Output:

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

What about n-ary negators (not3, not4, not5 ... notn) ?

Let's assume that I need to count the number of elements that are not between two numbers (lower bound limit and upper bound limit) in a collection (maybe an array).

.

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

.

How do I write the not3 negator?

Even more, do we have a generic not as a replacer of not1 and not2 in the same way as bind vs bind1st and bind2nd ?

Thank you


Solution

  • Since C++17 std::not_fn will be available:

    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