Let me show you something Kind of Cool. Create a set where less_equal
Is The Comparison Type, Then Insert 10 INTO The Set:
Set
S.insert (10); // Insert The value 10
Now Try Inserting 10 Again:
sinsert (10);
For this call to insert, the set Has to Figure out WHether 10 is already
Be Know That IT, But The Set Is Dumb As Toast, So It Has To
Check. To make it it easier to understand what happens when the set
Does this, we'll call the 10 That Was Initially Inserted 10 a and the 10
That We're Trying to INSERT 10 B.
The Set Runs THROUGH ITERNAL DATA STRUCTURES LOOKING for THE PLACE
To INSERT 10 B. IT Ultimately Has To Check 10 B To See IT's The Same As
10 a. The definition of "The Same" for Associative Containers Is Equiva-Lence
(See Item 19), So The Set Tests to See WHether 10 B Is Equivalent To
10 a. When Performing this Test, IT Naturally Uses The Set's Comparist
Function. in this Example, That's operator <=, BECAUSE WE Specified
Less_equal as the set's comparison function, and less_equal means Oper-ator <=.
The set thus checks to seehther this expression is true:
! (10 a <= 10 b) &&! (10 B <= 10 a) // TEST 10 A and 10 B for Equivalence
Well, 10 A and 10 B Are Both 10, SO it's Clearly True That 10 A <= 10 b.
Equally Clearly, 10 B <= 10 a. The Above Expression Thus Simplifies To
! (TRUE) &&! (TRUE)
And that Simplifies To
False && false
Which is Simply False. That IS, THE SET CONCLUDES THAT 10 A and 10 B Are
NOT Equivalent, Hence Not The Same, And Itthus Goes AboutInserting
10 b INTO The Container Alongside 10 a. Technically, this action Yields
Undefined Behavior, But The Nearly Universal Outcome IS That The Set
Ends Up with Two Copies of The Value 10, And That Means It's Not A Set
Any longer. by using less_equal asseur comparison type, we've cor-robted
THE CONTAINER! FURTHERMORE, Any Comparison Function Where Equal Values Return True Will Do The Same Thing. Equal Values Are, B
Definition, not equivalent! Isn't That Cool?
Okay, Maybe Your Definition of Cool Isn't The Same as Mine. Even SO,
You'll Still Want To Make Sure That The Comparison Functions you.com
For Associative Containers Always Return False for Equal Values. You'll
Need to be vigilant, however. it's surprisingly easy to run approverse t this
Constraint.
For Example, Item 20 Describes How To Write a Comparison Function
For Containers of String * Pointers Such That THE Container Sorts Its Con-Tents
By The Values of the strings insteadofthe value
That Comparison Function Sorts Them in Ascending ORDER, But Let's
Suppose You're in NEED of A Comparison Function for a Container of
String * Pointers That Sorts in decending Order. The Natural Thing to do
Is to grab the existing code and modify it. if're not Careful, you
Might Come Up with this, Where i've highlighted the change
Code in Item 20:
Struct stringptrgreater: // highlights showhow
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 here is to reverse the Sort Order by Negating The Test Inside The Comparison Function. Unfortunately, Negating "<" Doesn't Give You ">" (Which is what you want), IT gives you "> =". And you now Under-Stand That "> =", Because It Will Return True for Equal Values, IS AN Invalid Comparison Function for Associative Containers. The Comparison Type You Really Want Is this ONE: 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, all you need to repeember is what Return Value of a Comparison Function Indicates WHether ONE VALUE Precedes another in the sort order defined by That function. Equal Val-ues Never Precede One Another, So Comparison Functions Should Always Return False for Equal Values. Sigh. I know what you're thinking. You're thinking, "Sure, That Makes Sense For Set and Map, Because Those Containers CAN't Hold Duplicates. But What About Multiset and MultiMap? Those Containers May Contain Duplicates, So What Do I Care If The Container Thinks That Two Objects of Equal Value Aren't Equivalent? It Will Store Them Both, Which is What The Multi Containers Are Supposed to do. No qu, Right? " Wrong. To see why, let's go back to the Original Example, But this TIME We'll Use a multiset: MultiSet S.insert (10); // Insert 10 a S.insert (10); // INSERT 10 B S Now Has Two Copies of 10 in it, so we 'x @ @ ified Equal_range on it, we'll Get Back a Pair of Iterators That Define a RangeContaining Both Copies. But it's not possible. Equal_range, ITSNAME NOTWITHSTANDING, DOESN'TIFY A Range of equal value, it identifies A Rangeofquivalent Values. in this Example, S's Comparison FUNCTION Says That 10 A and 10 B Are Not Equivalent, So There's No Way That Both Can be in the range identified by equal_range. YOU SEE? UnsS Your Comparison Functions Always Return False for Equal Values, You Break All Standard Associative Containers, Regard-Less Of WHETER THEY.. Technically Speaking, Comparison Functions Used to Sort Associative Containers Must Define A "Strict Weak Order" over the objects the Compare. (Comparison Functions Passed to Algorithms Like Sort) Item 31) Are Similarly Constrained.) IF you're intended in the details of What It Means To Be a Strict Weak Ordering, You Can Find Them in Many CompRehensive Stl References, Including Josuttis' The C Standard Library [3], Austern's Generic Programming and the STL [4], and the SGI STL Web Site [21]. I've Never Found The Details Terribly Illuminat-ING, But One of the Requirements of A Strict Weak Ordering Bears Directly on this item. That Requirement is this any function defining a Strict Weak Ordering Must Return False if it's passed Two Copies of the Same Value. Hey! That is this item!