C++ std
命名空间包含辅助函数std::not1
和std::not2
.它们分别采用一元或二元谓词仿函数,并分别返回一个std::unary_negate
或std::binary_negate
谓词.
我想知道是否应该使用一些模板魔术来实现
templateinline enable_if_t ::value, unary_negate > not_(Predicate const&pred) { return unary_negate {pred}; } template inline enable_if_t ::value, binary_negate > not_(Predicate const&pred) { return binary_negate {pred}; }
它区分了pred
传递的参数以返回适当的谓词.当然,有一些奇怪的情况,传递的对象pred
有两种类型的运算符(一元和二元),当这不起作用时,但这些可以在不使用这个辅助函数的情况下处理.
在没有C++ 11功能的情况下计算出正确的过载并非完全无足轻重.当设计STL并且提出了这些函数对象时,甚至没有编译器能够编译这些函数中的一些.结果,一些功能比原本更难使用.例如,创建一个std::not_()
函数std::not()
是完全可行的(这是不可能的,因为它not
恰好是一个替代标记,因此不是一个可行的函数名称).也就是说,答案是:它主要是历史事故.
在函数重载的部分排序规则仍然相当混乱的时候,很可能会提出std::not1
并std::not2
提出这个规则.STL的主要提案是在1994年或1995年完成的(我无法在邮件存档中快速找到它).如果过载规则实际上已经根据STL提案进行了更改,我不会感到惊讶.
也就是说,在其他人加快速度并开发这些接口的改进版本之前花了几年的时间.Boost正在带领这些发展.
关于实现魔法,创建一个not_
与各种arities一起工作的函数实际上可能非常简单:
templateclass not_fn_t { std::decay_t pred; public: explicit not_fn_t(Pred p): pred(p) {} template bool operator()(A&&... a) const { return !this->pred(std::forward(a)...); } }; template not_fn_t not_fn(Pred&& pred) { return not_fn_t (std::forward (pred)); }
实际上,这std::not_fn()
与上次会议上投入C++工作文件的内容差不多.这是一个C++ 11的公式,但道德等价可以用早期版本的C++完成,只需扩展每个支持的arity的函数调用操作符(显然,没有完美的转发).