Valid STL Clause 21: Associate the strict weak order of the container (false is returned for equal values of the comparison function)

Source: Internet
Author: User
Document directory
  • Clause 21: always let the comparison function return false for equal values


Clause 21: always let the comparison function return false for equal values

Let me show you something cool. Create a set, use less_equal for the comparison type, and insert a 10:

Set <int, less_equal <int> S; // s is sorted by "<=" S. insert (10); // Insert 10

Now try to insert 10 again:


For this insert call, set must first determine whether 10 is already in it. We know that it is, but set is a wooden head, and it must be checked. To help you understand what happened, we call 10 in set as 10a at the beginning, and the 10 being inserted is called 10B.

Set traverses its internal data structure to find out which one is suitable for inserting 10B. Eventually, it always checks whether 10b is the same as 10a. The associated container defines "same" as equivalence (see clause 19), so set test 10b is equivalent to 10a. When performing this test, it naturally uses the set comparison function. In this example, operator <=, because we specify the set comparison function as less_equal, and less_equal indicates operator <=. Therefore, set calculates whether the expression is true:

! (10a <= 10B )&&! (10B <= 10a) // test whether 10a and 10b are equivalent.

Oh, both 10a and 10b are 10. Therefore, 10a <= 10b must be true. It is also clear that 10b <= 10a. Therefore, the above expression is simplified

!(true) && !(true)


false && false

The result is false. That is to say, set concluded that 10a is not equivalent to 10B, so it is different, so it inserts 10b next to 10a in the container. Technically speaking, this practice leads to undefined behavior, but the general result is that set ends with two copies of 10 values, that is, it is no longer a set. By using less_equal as our comparison type, we destroy the container! In addition, any comparison function that returns true for equal values will do the same thing. According to the definition, equal values are not equivalent! Is it cool?

OK. Maybe your definition of cool is different from mine. Even so, you still need to make sure that the comparison function you use on the associated container always returns false for the same value. However, you need to be vigilant. Violations of this rule can easily lead to surprising consequences.

For example, Clause 20 describes how to write a comparison function so that the container containing the string * pointer sorts the string value instead of the pointer value. The comparison function is sorted in ascending order, but now we assume that you need the comparison function of the string * pointer container in descending order. Naturally, it is modified by grasping the ready-made code. If you are not careful, you may do this. I have added some of the changes to the Code in Clause 20:

Struct stringptrgreater: // highlight the public binary_function <const string *, // This code and the 89-page change const string *, // be careful, this code is flawed! Bool> {bool operator () (const string * ps1, const string * PS2) const {return! (* PS1 <* PS2); // the opposite is the old test;} // This is not correct !};

The idea here is to reverse the results of the comparison function. Unfortunately, the reverse "<" won't give you (what you expect) ">", and it gives you "> = ". As you know, because it returns true for equal values, it is an invalid comparison function for associated containers.

The comparison type you really need is:

Struct stringptrgreater: // for associated containers, public binary_function <const string *, // This is a valid comparison type const string *, bool> {bool operator () (const string * ps1, const string * PS2) const {return * PS2 <* PS1; // returns * PS2 whether} // greater than * PS1 (that is,}; // The sequence of switching operands)

To avoid falling into this trap, you must remember that the return value of the comparison function indicates whether a value is greater than the other value in the sorting method defined by this function. The same value should never be greater than the other. Therefore, the comparison function should always return false for the same value.


I know what you're thinking. You are thinking, "of course, this makes sense for set and map, because these containers cannot hold copies. But how about Multiset and multimap? Those containers can hold copies, and those containers may contain copies. So what do I need to know if the containers think that two objects with equal values are not equivalent? It stores both of them, which is exactly what the multi series containers support. No problem, right ?"

Error. I want to know why. Let's go back to the header to see the original example, but this time we use a mulitset:

Multiset <int, less_equal <int> S; // s is still sorted by "<=" s. insert (10); // insert 10as. insert (10); // insert 10b

Now, there are two 10 copies in S, so we expect that if we make a performance_range on it, we will get an iterator pointing to the range containing the two copies. But that is impossible. Equal_range, which is called this name, does not indicate the range of equal values, but the range of equivalent values. In this example, the comparison function of S indicates that 10a and 10b are not equivalent, so it is impossible for them to appear in the range indicated by performance_range at the same time.

Do you understand? Unless your comparison functions always return false for equal values, you will break all the standard associated containers regardless of whether they allow storage of duplicates.

Technically, the comparison functions used to sort associated containers must define a strict weak ordering on the objects they compare )". (Comparison functions passed to algorithms such as sort (see section 31) also have the same restrictions ). If you are interested in the details of the strict weak ordinal meaning, you can find them in many comprehensive STL reference books, such as josutis's "The C ++ standard library" [3](Translated Chinese Version C ++ library p176), Austern's generic programming and the STLTranslation: Generic programming and STL[4], and sgi stl website [21]. I have never found this detail so important, but a requirement for strict weak ordering directly points to this provision. That requirement is that all functions that define strict weak sequentions must return false when two copies of the same value are passed in.




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.