Reputation: 51
I'm trying to use a std::string as a key in a std::map however, i'm unable to find() correctly. My code is somewhat complicated and large so this is a small program that demonstrates the problem I'm having. If someone could tell me why this doesn't work, i'd be very grateful.
Thanks.
#include <stdio.h>
#include <string>
#include <map>
struct comparer
{
public:
bool operator()(const std::string x, const std::string y)
{
return x.compare(y)==0;
}
};
int main(int argc, char *argv[])
{
std::map<std::string, int, comparer> numbers;
numbers.insert(std::pair<std::string,int>("One",1));
numbers.insert(std::pair<std::string,int>("Two",2));
numbers.insert(std::pair<std::string,int>("Three",3));
numbers.insert(std::pair<std::string,int>("Four",4));
numbers.insert(std::pair<std::string,int>("Five",5));
std::map<std::string, int, comparer>::iterator it=numbers.find("Three");
if(it!=numbers.end())
printf("The number is %d\n",(*it).second);
else
printf("Error, the number is not found\n");
}
Upvotes: 5
Views: 31034
Reputation: 1650
The custom compare operation is not usually required (you can normally just use std::map<std::string, int>
), but for a bit of optimization when using (not very short) strings as keys and passing a string constant (char* constant) (or std::string_view
or any other type that can be easily compared to std::string
without converting to std::string
) to contains()
or find()
, see https://www.cppstories.com/2021/heterogeneous-access-cpp20/.
(Also your comparer::operator()
could take const string references, to avoid copying there as well: bool operator()(const std::string& x, const std::string& y) const
...)
Upvotes: 0
Reputation: 7
This should work:
#include <stdio.h>
#include <string>
#include <map>
struct comparer
{
public:
bool operator()(const std::string x, const std::string y) const
{
return x.compare(y)==0;
}
};
int main(int argc, char *argv[])
{
std::map<std::string, int, comparer> numbers;
numbers.insert(std::pair<std::string,int>("One",1));
numbers.insert(std::pair<std::string,int>("Two",2));
numbers.insert(std::pair<std::string,int>("Three",3));
numbers.insert(std::pair<std::string,int>("Four",4));
numbers.insert(std::pair<std::string,int>("Five",5));
std::map<std::string, int, comparer>::iterator it=numbers.find("Three");
if(it!=numbers.end())
printf("The number is %d\n",(*it).second);
else
printf("Error, the number is not found\n");
}
Upvotes: -1
Reputation: 131789
std::map
(and set
and their multi
variants) enforce strict weak ordering.
x.compare(y) == 0;
Will return true if the strings are equal. The comparer should return whether the first string should go before the second string. Either return x.compare(y) < 0
or just leave your comparision functor out.
Upvotes: 3
Reputation: 9031
comparer::operator()
should return value of operator <, not of operator ==.
Upvotes: 3
Reputation: 143071
Remove your comparer
and it will work just fine. The thing is, you didn't implement it properly. It should return true
if x
is to be placed before y
. Or change ==0
to <0
or >0
(it doesn't really matter).
Upvotes: 6