I have an std::map<string, string>
with a custom predicate:
struct PredIgnoreCase {
bool operator()(const std::string& str1, const std::string& str2) const {
std::string str1NoCase(str1), str2NoCase(str2);
std::transform(str1.begin(), str1.end(), str1NoCase.begin(), tolower);
std::transform(str2.begin(), str2.end(), str2NoCase.begin(), tolower);
return (str1NoCase < str2NoCase);
}
};
Now given
typedef std::map<std::string, std::string> DIRECTORY_WITHCASE;
typedef std::map<std::string, std::string, PredIgnoreCase> DIRECTORY_NOCASE;
I initialize
// Case-sensitive directory: case of string-key plays no role
DIRECTORY_WITHCASE dirCaseSensitive{
make_pair("John", "2345764"),
make_pair("JOHN", "2345765"),
make_pair("Sara", "42367236"),
make_pair("Jack", "32435348"),
};
And then when I initialize
DIRECTORY_NOCASE dirCaseInsensitive(dirCaseSensitive.begin(),
dirCaseSensitive.end());
dirCaseInsensitive
prints
Jack - >32435348
JOHN - >2345765 <---- John in upper case
Sara - >42367236
However, if I initialize the dirCaseInsensitive
like:
DIRECTORY_NOCASE dirCaseInSensitive{
make_pair("John", "2345764"),
make_pair("JOHN", "2345765"),
make_pair("Sara", "42367236"),
make_pair("Jack", "32435348"),
};
It outputs correct map:
Jack - >32435348
John - >2345764 <----- John in lower case
Sara - >42367236
Why would different constructors of the same map, give different results?
The ordering matters here. If you switch make_pair("JOHN", "2345765")
with make_pair("John", "2345764")
in your dirCaseInSensitive
construction, you will see the first output.
The case here is that when you first create:
DIRECTORY_WITHCASE dirCaseSensitive{
make_pair("John", "2345764"),
make_pair("JOHN", "2345765"),
make_pair("Sara", "42367236"),
make_pair("Jack", "32435348"),
};
due to ordering of the keys, your "JOHN"
key is placed as the first key (before the "John"
key). Now, if you try to use that very map to initialize the second one, it will first insert the ("JOHN", "2345765")
pair and then see the ("John", "2345764")
pair. It will case-insensitive compare the keys and figure out they are equivalent, so it won't insert the lowercase "John"
pair.
So, to summarize, it's not really the usage of constructors. It's the surprising mix of your order of provided pairs and the ordering of they key, which do not match.
Because the order of pairs in each case is different. In the first case the constructor of dirCaseInsensitive
is called (in effect) with the pairs in this order.
make_pair("JOHN", "2345765"),
make_pair("Jack", "32435348"),
make_pair("John", "2345764"),
make_pair("Sara", "42367236"),
This is the order of the pairs in dirCaseSensitive
(assuming ASCII or similar character set).
In the second case the constructor of dirCaseInsensitive
is called with pairs in the order given by the initialiser list.
make_pair("John", "2345764"),
make_pair("JOHN", "2345765"),
make_pair("Sara", "42367236"),
make_pair("Jack", "32435348"),
So you can see in the first case "JOHN" is before "John" so "JOHN" gets inserted but in the second case it's the other way around.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With