Item 21: Always let comparison functions return false for the same element
Let me show some more cool things. Build a set, comparing type is Less_equal, then INSERT 10:
Set
S.insert (10); // Insert The value 10
Try Now INSERT once 10:
sinsert (10);
For this INSERT call, SET must first understand if 10 is already in it. We know that it is already in it, but SET is wood, it must perform check. In order to make it easy to make what happen, we will already be called 10A in the 10A, which is trying to call 10b.
SET traverses its internal data structure to look for the location of 10B. Finally, it always checks if 10b is the same as 10A. Associated container definitions of "The same" is Equivalence (see Item 19) (WQ Note: Equivalence should refer to "Mathematical Same", Two Elements Are Equal if Neither Is Less Than THE OTHER, see "The C Standard Library" Chinese version P82, English version of the electronic P77; Equality refers to "Logic Isas", using Operator == (), see "The Standard Template Library" English electronic version P30) Therefore, the SET test 10b is a mathematical equivalent to 10A. When this test is executed, it is naturally a comparison function using the SET. In this example, it is Operator <= because we specify the comparison function of the SET is LESS_EQUAL, while less_equal is Operator <=. So, the SET will calculate whether this expression is true:
! (10 a <= 10 b) &&! (10 B <= 10 a) // TEST 10 A and 10 B for Equivalence
Ok, 10A and 10 B are 10, so 10A <= 10b is definitely true. Similarly, 10A <= 10b. The above expression is simplified
! (TRUE) &&! (TRUE)
Again is simplified
False && false
The result is of course false. That is, the conclusions derived by the SET are not equal to 10B, so it is not the same, so it puts 10b to add 10A to the container. Technically, this action leads to undefined behaviors, but the usual result is that the set is ended in a copy of the elements that have two 10, that is, it is no longer a set. By using Less_equal as our comparison type, we destroy the container! In addition, all comparison functions that return TRUE for the same element will do the same thing. Depending on the definition, the same elements are not equal! Is it cool?
Ok, maybe you are not the same for cool definitions. Even if this is the case, you still need to make sure that the comparison function you use on the associated container always returns FALSE for the same element. However, you need to be vigilant. The violation of this rule is easy to surprise.
For example, ITEM 20 describes how to write a comparison function such that the container that accommodates the String * pointer is sorted according to the value of String, rather than sorting the pointer value. The comparison function there is sorted in ascending order, but we now assume that you need a comparison function in descending order. Naturally, it is a ready code to modify it. If you are not careful, you may do this, I have already increased the part of the Item 20 in the Item 20: Struct Stringptrgreater: // Highlights Show How
Public binary_function Const string *, // from page 89. BEWARE, Bool> {// this code is flawed! BOOL Operator () (const string * ps1, const string * ps2) Const { Return! (* ps1 <* ps2); // Just Negate The Old Test; } // this is incorrect! } The idea is to reject the comparison function inside the comparison function. Unfortunately, reflect "<" will not give you (you expect) ">", it gives you "> =". You now know, because "> =" will return True to the same element, which is not a valid comparison function. The type of comparison you really need is this: Struct stringptrgreater: // this is a valid Public binary_function Const string *, // associative containers Bool> { BOOL Operator () (const string * ps1, const string * ps2) Const { Return * ps2 <* ps1; // return WHETHER * PS2 } // precedes * ps1 (I.E., SWAP // the order of the }; // Operands) To avoid falling into this trap, what you want to remember is that the return value of the comparison function is indicated under the sort mode defined in this function, and an element should be in another. The same element is never ahead of another, so the comparison function should always return false for the same element. Ugh. I know what you are thinking. You are thinking, "Of course, this is very meaningful for Set and MAP because these containers cannot accommodate the copy. How about MultiSet and MultiMap? Those containers can contain a copy, and those containers may contain copies, so if the container is considered Two the same element objects do not equiven, what do I need to pay attention to (SO What Do I Care if The Container Thinks That Two Objects of Equal Value Aren't Equivalent?)? It will store both all stores, this is It is the thing to support the Multi series container. No problem exists, right? " I want to know why, let us go to see the original example, but this time it is a MULITSET: MultiSet S.insert (10); // Insert 10 a S.insert (10); // INSERT 10 B Now, there is two elements of 10 elements, so we expect, if we do an equal_range on it, we will get a pair of Iterator to point out the range of the two copies. But that is impossible. Equal_Range, name is not realistic, not to indicate the range of the same element, but the range of equivalents. In this example, the comparison functions of S say 10a and 10b are non-equivalents, so it is impossible to allow them to simultaneously appear within the range indicated by Equal_Range. Do you understand it? Unless your comparison function always returns false for the same element, you will break all associated containers, whether or not they allow storage of the copy. Technically, a comparison function for associative containers must define a "strict weak ordering" on the object they compare. (The comparison function of the generic algorithm for Sort (Item 31) is also limited). If you are interested in Strict Weak ORDERING, you can find in many STL guidance books, such as Josuttis's "THE C Standard Library" (WQ Note: Chinese P176, English Edition Electronic P156), Austern "generic programming and The STL ", and SGI STL website. I have never discovered this detail so important, but a Strict Weak Order requirement directly aimed on this item. That requirement is that any function defined a strict weak ordering must return false when it is passed to two copies of the same element. Hey! That is this item!