What does std::includes actually do?

℡╲_俬逩灬. 提交于 2019-11-29 10:43:30

问题


From the standard, std::includes:

Returns: true if [first2, last2) is empty or if every element in the range [first2, last2) is contained in the range [first1, last1). Returns false otherwise.

Note: as this is under [alg.set.operations], the ranges must be sorted

Taking this literally, if we let R1=[first1, last1) and R2=[first2, last2), this is evaluating:

∀a∈R2 a∈R1

However, this is not what is actually being evaluated. For R1={1} and R2={1,1,1}, std::includes(R1, R2) returns false:

#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';
}

Live on Wandbox

This is surprising. I verified it with both libstdc++ and libc++, but it seems unlikely to me that this would be a bug in the standard library implementation, considering it's part of the algorithms library. If this isn't the algorithm that std::includes is supposed to run, what is?


回答1:


I posted this in the cpplang slack, and Casey Carter responded:

The description of the algorithm in the standard is defective. The intent is to determine [if] every element in the needle appears in order in the haystack.

[The algorithm it actually performs is:] "Returns true if the intersection of sorted sequences R1 and R2 is equal to R2"

Or, if we ensure we are certain of the meaning of subsequence:

Returns: true if and only if [first2, last2) is a subsequence of [first1, last1)

link to Casey Carter's message




回答2:


I believe you're trying to check if a includes b in your example, a doesn't include b but b does include a. If you swap b and a it will return true, since a is included in b.

I hope I'm not missing something obvious.

#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';
}

What I've understood by playing around with algorithm is, when you type includes(R2, R1) it checks if R2 owns R1 as a subgroup, if yes returns true if not returns false. Also if it's not ordered throws an error: sequence not ordered.




回答3:


As always when reading the standard, you must read the unwritten words.

Focus on the intent not just the letter. (The wording of the standard was often found to be vague, incomplete, self-referential, or contradictory.)

Read the introduction of section "28.7.6 Set operations on sorted structures [alg.set.operations]" :

This subclause defines all the basic set operations on sorted structures. They also work with multisets containing multiple copies of equivalent elements. The semantics of the set operations are generalized to multisets in a standard way by defining set_­union() to contain the maximum number of occurrences of every element, set_­intersection() to contain the minimum, and so on.

So it's perfectly clear that the words in the description of includes:

Returns: true if [first2, last2) is empty or if every element in the range [first2, last2) is contained in the range [first1, last1). Returns false otherwise.

must be ignored. You need to know a priori what multiset operations are, what "includes" means for two multisets, ignore the description and rebuild in your head what was the obvious intent.

Multiset inclusion:

A is included in B iff A union B = B.

This is true for sets or multisets.



来源:https://stackoverflow.com/questions/50516031/what-does-stdincludes-actually-do

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!