std :: includes实际上做了什么?

时间:2018-05-24 18:36:24

标签: c++ language-lawyer c++17 stl-algorithm

来自the standard, true

  

如果[first2, last2)为空,或者[first2, last2)范围内的每个元素都包含在[first1, last1)范围内,则返回false。   否则返回R1=[first1, last1)

注意:由于这是在 [alg.set.operations] 下,必须对范围进行排序

从字面上看,如果我们让R2=[first2, last2)∀a∈R2 a∈R1 进行评估,那就是:

R1={1}

但是,这不是实际评估的内容。对于R2={1,1,1}std::includes(R1, R2)#include <algorithm> #include <iomanip> #include <iostream> #include <vector> int main() { std::vector<int> a({1}); std::vector<int> b({1,1,1}); // Outputs 'false' std::cout << std::boolalpha << std::includes(a.begin(), a.end(), b.begin(), b.end()) << '\n'; } 返回false:

std::includes

Live on Wandbox

这令人惊讶。我用libstdc ++和libc ++验证了它,但是我认为这不是标准库实现中的一个错误,因为它是算法库的一部分。如果这不是{{1}}应该运行的算法,那么是什么?

3 个答案:

答案 0 :(得分:30)

我在cpplang slack和Casey Carter responded中发布了这个:

  

标准中的算法描述有缺陷。目的是确定[if]针中的每个元素按顺序出现在大海捞针中。

     

[它实际执行的算法是:]&#34;如果排序的序列R1和R2的交集等于R2&#34,则返回true;

或者,如果我们确保我们确定subsequence的含义:

  

返回:当且仅当[first2,last2]是[first1,last1]的子序列时返回true

link to Casey Carter's message

答案 1 :(得分:3)

我相信您正在尝试检查示例中的a是否包含ba不包括b,但b确实包括a。如果您交换ba,则会返回true,因为a中包含b

我希望我不会错过一些明显的东西。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> a({1});
    std::vector<int> b({1,1,1});

    // Outputs 'true'
    std::cout << std::boolalpha
        << std::includes(b.begin(), b.end(), a.begin(), a.end()) << '\n';
}

通过使用算法我已经理解的是,当您键入includes(R2, R1)时,它会检查R2是否拥有R1作为子组,如果是,则返回{{1}如果不返回true。如果没有订购,也会引发错误:false

答案 2 :(得分:-1)

与阅读标准一样,您必须阅读未写的单词

不仅要关注字母,还要关注意图。 (该标准的措词经常被发现含糊,不完整,自我参照或自相矛盾。)

阅读“ 28.7.6 Set operations on sorted structures [alg.set.operations]”部分的介绍:

  

本节定义了排序后的所有基本设置操作   结构。他们还使用包含多个副本的多集   等效元素。 设置操作的语义是   通过将set_­union()定义为以标准方式将其推广到多集   包含每个元素的最大出现次数,   set_­intersection()包含最小值,以此类推

因此,非常清楚includes描述中的单词:

  

返回:如果[first2,last2)为空,或者如果   范围[first2,last2)包含在范围[first1,last1)中。   否则返回false。

必须忽略。您需要先验一下先验是什么多集操作,两个多集的“包含”含义是什么,请忽略描述并在脑海中重建明显的意图。

多集包含:

A包含在B中 iff 联合B = B。

这对集合或多集合是正确的。