C++中std::search的二元谓词实现要求

7
在这个网站上,它指出传递给std::search的二元谓词的约束之一是:

Type1和Type2的类型必须是这样的,即ForwardIt1和ForwardIt2类型的对象可以被取消引用,然后隐式转换为Type1和Type2。

然而,在C++国际标准文档中,我没有看到这样的约束。我想知道这个约束是否在C++国际标准文档中明确说明,并且它属于哪个部分。此外,如果不是这样,为什么要将此约束放置在std::search函数上,因为有可能存在两种不同的类型,虽然不能隐式转换,但定义了相等运算符重载?


@bolov 在 alg.search 中没有明确的要求。 - llllllllll
我更新了标题以使其更准确。 - cogle
@liliscent 是的,没错。好吧,可能有点隐晦,但那不是重点。 - bolov
3个回答

6
这是网站上的一个错误。
该参数说明来自this template。它不能区分仅作为pred(*first1, *first2)调用的二元谓词和既作为pred(*first1, *first2)又作为pred(*first2, *first1)调用的二元谓词。
进一步挖掘: 看起来这个编辑父模板cast req2使用添加了一个命名参数,它控制着它是说"both"还是"respectively"。 eq变体没有这个新参数的传递。我没有编辑权限将其添加到模板和std::search的条目中。

网站模板中的引语...好答案! - llllllllll
{{cast req2}} 对于这种情况也错误地检查了 bidirectional(MediaWiki 的 #if 是“如果为空”检查,而不是“如果为真”检查)。我已经对模板进行了检测,以便找出我们在使用此默认值的位置,以便可以修复它们(通过更改默认值或使用 bidirectional=false 进行抑制)。 - T.C.
看起来默认的 true 只在五个页面上使用了,而且它们都不应该使用。已修复。 - T.C.

3
一个BinaryPredicate的要求在[algorithms.requirements]/7中说明:

每当一个算法期望一个应用于解引用两个相应迭代器的结果或者解引用一个迭代器和类型T(当T是函数签名的一部分时)时返回一个可测试为true值的函数对象时,就会使用BinaryPredicate参数。换句话说,如果一个算法将BinaryPredicate binary_pred作为其参数,并将first1first2作为其迭代器参数,它应该在上下文转换为bool([conv])的构造binary_­pred(*first1, *first2)中正确地工作。 BinaryPredicate总是将第一个迭代器的value_­type作为其第一个参数;也就是说,在这些情况下,当T value是函数签名的一部分时,它应该在上下文转换为bool([conv])的构造binary_­pred(*first1, value)中正确地工作。 binary_­pred不应通过解引用的迭代器应用任何非常量函数。

没有要求从解引用ForwardIt2构造Type1。cppreference中OP引用的“both”一词是不准确的。


我明白了,但是我没有看到那段话中明确说明 first1first2 这两种类型必须隐式转换为同一类型,这是网站声明的一个限制条件。我猜这是否意味着我提供的链接有错误的解释? - cogle
@cogle 我找不到任何关于“可转换为单一类型”的说明。你能指出来吗? - llllllllll
1
然后隐式转换为同时 Type1 和 Type2,与然后隐式转换为分别 Type1 和 Type2。 - Caleth
是的,根据链接,似乎这是我的笔误,尽管它指出它们必须从“Type 1”隐式转换为“Type 2”,反之亦然。这就是我认为@Caleth所指出的。 - cogle

1

好的,我终于看到你的困惑了。这是由于“both”一词的用法引起的。

意思应该是以下两个条件都必须为真:

  • 类型Type1必须使得ForwardIt1类型的对象可以被取消引用,然后隐式转换为Type1

  • 类型Type2必须使得ForwardIt2类型的对象可以被取消引用,然后隐式转换为Type2


你可以在25.2.13搜索[alg.search]中找到要求:

§25.2.13 Search [alg.search]

template<class ForwardIterator1, class ForwardIterator2,
         class BinaryPredicate>
ForwardIterator1
search(ForwardIterator1 first1, ForwardIterator1 last1,
       ForwardIterator2 first2, ForwardIterator2 last2,
       BinaryPredicate pred);
  1. Returns: The first iterator i in the range [first1,last1 - (last2-first2)) such that for every non-negative integer n less than last2 - first2 the following corresponding conditions hold: *(i + n) == *(first2 + n), pred(*(i + n), *(first2 + n)) != false. Returns first1 if [first2, last2) is empty, otherwise returns last1 if no such iterator is found.
相关的是条件:
pred(*(i + n), *(first2 + n)) != false

这意味着pred(*(i + n), *(first2 + n))是有效的。也就是说,*(i + n)*(first2 + n)可以作为参数传递给pred。意味着pred的第一个参数必须可以从对ForwardIterator1进行解引用构造,而pred的第二个参数必须可以从对ForwardIterator2进行解引用构造。


1
我认为我们都误解了 OP 的问题,事实上,OP 正在询问“pred”的“第一个”参数是否必须可以从“ForwardIterator2”的解引用构造。您的引用不需要它。但是 OP 在 cppreference 引用中使用的“both”一词要求这样做。 - llllllllll
嗯...是的,也许措辞有点不恰当。但在我看来,他们的意思很明显,FI1可转换为T1,FI2可转换为T2。 - bolov

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