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