C++中的谓词是什么?

52

你能举个例子或提供一个相关主题的链接吗?


77
@Mr E:Stack Overflow的好处在于,越来越多与编程有关的Google搜索结果都将链接到这里。如果这些问题在这里没有得到解答,那么这种情况永远不会发生,SO也永远无法达到临界质量。所以,“谷歌一下”从来不是一个令人满意的答案。 - Clifford
16
@Mr E: 你自己尝试过那个搜索了吗?排名最靠前的结果所给出的定义是错误的,因此对于至少尝试寻求比普通人更可能给出正确答案的人提问者要给予+1的评价。 - Steve Jessop
2
@munish:在C++中,它特指STL算法的谓词参数及类似用途。你的问题可能与此有关,也可能不是,我更倾向于一般语法意义上的解释,所以我学到了新知识,很高兴你没有只是通过谷歌搜索得到答案,因为我认为这个问题确实增加了SO库的价值。不过,我建议你将正文内容更改为更为详细和扩展的内容,避免不必要的关闭和负评。 - Clifford
6
@MrE 我有,这就是我来到这里的原因... - fauxCoder
4
这个问题为什么可能被认为“不是一个真正的问题”?难道标题不足以回答它吗? - 3bdalla
显示剩余5条评论
4个回答

60

谓词是一个返回布尔值或具有 bool operator() 成员函数的 C++ 函数。一元谓词接受一个参数,二元谓词接受两个参数,以此类推。谓词可以回答特定算法的以下问题:

  • 这个元素是否是我们要找的?
  • 两个参数中的第一个是否按照我们的排序方式排在前面?
  • 这两个参数是否相等?

几乎所有的 STL 算法 都将谓词作为最后一个参数。

您可以使用标准、自定义和/或谓词生成类(这里有一个很好的参考资料)构建新的谓词。


15
谓词不一定要是函数,它们也可以是函数对象(functor)。至于标准算法的目的,谓词返回的东西不一定是bool类型或具有operator bool(),可以返回任何可测试为真或假的内容。因此,可以将转换为bool的内置类型,例如指针,也视为合格。 - Steve Jessop

14

这与C++(甚至计算机语言)无关,它是自然语言语法中的一个概念。比如,在类似“大门打开了”的陈述中,“打开了”部分是谓语,其结果要么为真,要么为假。因此,如果你有一个名为cGate的类,并拥有一个成员函数bool cGate::isOpen(),这样的函数将会是一个谓词。

基本上,如果该函数询问对象状态或值并且结果只能为真或假,那么它就是一个谓词。


14
C++标准将"Predicate"定义如下(25/7):
当算法期望一个函数对象时,Predicate参数被用于以下情况: 当应用于对应迭代器解引用结果返回可测试为true值的函数对象。换句话说,如果一个算法将Predicate pred作为其参数,并将first作为其迭代器参数,则在if(pred(*first)){...}结构中应正确工作。pred函数对象不应通过解引用的迭代器应用任何非常量函数。该函数对象可以是指向函数的指针,或者是具有适当函数调用运算符的类型的对象。
有两个参数的BinaryPredicate还有类似的定义。
因此,它是一个具有operator()重载的函数或对象,其操作包括:
  • 接受单个参数。在算法中,参数类型可以从问题算法的解引用迭代器的类型隐式转换,也可以是对这种类型的const引用,或者紧贴着迭代器不是const_iterator 的非const引用。
  • 返回一个可以在if语句(因此根据C++的语言规则,同样可以在while循环等语句中)进行真实性测试的值。
  • 不修改其参数(至少,在参数类型是const-correct的情况下不修改......)。
此外,由于许多算法没有指定它们执行操作的确切顺序,因此如果您的Predicate不一致(即结果依赖于除调用之间可以更改的输入值之外的任何内容),则可能会出现不可预测的行为。除了算法之外,<functional> 中的逻辑否定器 not1 还需要一个 Predicate 模板参数。在这种情况下,还有一个额外的要求 (20.3/5):
为了使适配器和其他组件能够操作带有一个或两个参数的函数对象,要求相应地提供类型定义。对于带有一个参数的函数对象,需要提供 typedefs argument_type 和 result_type,而对于带有两个参数的函数对象,则需要提供 first_argument_type、second_argument_type 和 result_type。请注意保留原文中的 HTML 标签格式。

7
一个谓词是一个简单的函数,根据它的输入是否满足某个条件返回true或false。通常情况下,谓词函数应该是纯的;当给定相同的输入时,它应该总是返回相同的结果(因此bool isDateInPast(Date &date)将是一个糟糕的谓词)。例如,它们经常被用作STL排序例程的回调函数(即“输入a是否小于输入b?”)。

那个链接说它还必须是一个“一元”函数。 - Simon Nickerson
@Simon:是的,那不是一个非常通用的链接。我会从我的答案中删除它。 - Oliver Charlesworth
谓词通常在STL 搜索例程中使用,例如copy_if。是的,它们是一元的。排序函数不被视为谓词。 - Ben Voigt
2
@Ben:Compare参数的要求比BinaryPredicate参数的要求严格得多。比较器必须返回truefalse(而不是任何可测试真值),当然还必须实现一个严格弱序。但由于C++0x使用了术语“Predicate”而不是“UnaryPredicate”,我们不得不得出结论,虽然“binary predicate”在英语中是“predicate”,但BinaryPredicate在标准语中并不是Predicate。疯狂的事情 :-) - Steve Jessop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接