0

一元和二元否定符的用处很容易理解。

一元否定符( 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作为 and 的替代者not1not2其方式与bindvs bind1stand相同bind2nd

谢谢

4

3 回答 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));

魔杖盒示例

于 2017-01-23T11:03:54.753 回答
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";
}

[在 Coliru ] [在 Godbolt ]

我还没有测试所有可能的变体,所以这可能仍然是错误的。

于 2017-01-23T11:38:01.270 回答
0

如何编写 not3 否定符?

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

更重要的是,我们是否有一个通用的 not 作为 not1 和 not2 的替代者,就像 bind vs bind1st 和 bind2nd 一样?

一旦 C++17 正式发布,我们就会这样做。建议引入std::not_fn作为替代,std::not1然后std::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)...);
    };
}
于 2017-01-23T11:18:52.273 回答