如何写一个n元否定器?
How to write a n-ary 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";
输出:
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
作为 not1
和 not2
的替代品,就像 bind
vs bind1st
和bind2nd
?
谢谢
因为 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));
How do I write the not3 negator?
符合 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);
}
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 ?
一旦 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)...);
};
}
你可以自己写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]
我还没有测试所有可能的变体,所以这可能仍然存在问题。
一元和二元否定符的用处很容易理解。
一元否定符示例 (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
作为 not1
和 not2
的替代品,就像 bind
vs bind1st
和bind2nd
?
谢谢
因为 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));
How do I write the not3 negator?
符合 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);
}
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 ?
一旦 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)...);
};
}
你可以自己写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]
我还没有测试所有可能的变体,所以这可能仍然存在问题。