为什么有std :: not1()和std :: not2()而不是一个重载的std :: not_()?

时间:2015-12-17 08:54:41

标签: c++ template-meta-programming sfinae

C ++ std命名空间包含辅助函数std::not1std::not2。它们分别采用一元或二元谓词仿函数,并分别返回std::unary_negatestd::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}; }

区分传递的参数pred以返回适当的谓词。当然,有一些奇怪的情况,传递的对象pred有两种类型的运算符(一元和二元),当这不起作用,但这些可以在不使用这个辅助函数的情况下处理。

2 个答案:

答案 0 :(得分:9)

在没有C ++ 11功能的情况下计算出正确的过载并非完全无足轻重。当设计STL并且提出这些功能对象时,甚至没有编译器能够编译这些功能中的一些。结果,一些功能比原本更难使用。例如,创建data.json函数完全可行(std::not_()是不可能的,因为std::not()恰好是替代令牌,因此不是{ta}可行的功能名称)。也就是说,答案是:它主要是历史性事故。

在函数重载的部分排序规则仍然相当混乱的时候,很有可能提出notstd::not1。 STL的主要提议是在1994年或1995年完成的(我无法在How do I download a file over HTTP using Python?中快速找到它)。如果响应STL提案实际更改了过载规则,我不会感到惊讶。

也就是说,在其他人加快速度并开发这些接口的改进版本之前,花了几年的时间。 mailing archive带领着这些发展。

关于实现魔法,创建一个与各种arities一起使用的std::not2函数实际上可能非常简单:

not_

实际上,这几乎就是在上次会议上被评为C ++工作文件Boost的内容。这是一个C ++ 11的公式,但道德等价可以用早期版本的C ++完成,只需扩展每个支持的arity的函数调用操作符(显然,没有完美的转发)。

答案 1 :(得分:2)

2013年有这样的提案:N3699 A proposal to add a generalized callable negator。这已经持续了一段时间(最新版本是N4022)并且看起来像should make it into the second Library Fundamentals TS;它出现在Library Fundamentals TS 2 draft n4564中的 func.not_fn 部分。

标准中存在not1not2的原因是它们已经存在了相当长的一段时间,因为在存在支持单个否定符所必需的元编程技术之前。