0

I want to implement an unordered_map<string, string> that ignores case in the keys. My code looks like:

    std::unordered_map<std::string, std::string> noCaseMap()
    {
        struct hasher {
            std::size_t operator()(const std::string& key) const {
                return std::hash<std::string>{}(toLower(key));
            }
        };
        std::unordered_map<std::string, std::string, hasher> ret;
        return ret;
    }

but XCode flags the return statement with this error:

foo.cpp:181:20 No viable conversion from returned value of type 'unordered_map<[2 * ...], hasher>' to function return type 'unordered_map<[2 * ...], (default) std::hash<std::string>>'

I tried casting ret to <std::unordered_map<std::string, std::string>>, but XCode wasn't having it.

I tried making my hasher a subclass of std::hash<std::string> but that made no difference.


Edit: this is a slight oversimplification of the problem; I know I also have to implement a case-insensitive equal_to() functor as well.

8
  • 3
    You can't. There's a reason it's part of the type: efficiency. What you can do is e.g. store everything lowercase. Commented Nov 4, 2022 at 21:24
  • Yes, I had an earlier implementation that did store everything lower case, but I want to return this struct to client code that might not convert the key to lower case before reading from the map. Commented Nov 4, 2022 at 21:27
  • 1
    But if you cant, you can't. 😕 Make your comment an answer, and I'll accept it. Commented Nov 4, 2022 at 21:30
  • 3
    Why not declare hasher at namespace scope and adjust the return type? Also note that std::unordered_map<std::string, std::string, hasher> probably doesn't do what you want: this just uses a worse hash function, but it doesn't change anything about key equality. Inserting values for "a" and "A" into your map will still result in 2 entries, but those 2 entries will always result in a hash collision. Commented Nov 4, 2022 at 21:40
  • 1
    you can return a std::unordered_map<Foo, std::string> where Foo can be constructed from a string and stores a lower case string. When the user then looks up the_map["AsDf"] then their string will be converted to lower case Commented Nov 4, 2022 at 22:23

1 Answer 1

2

You can't. There's a reason it's part of the type: efficiency. What you can do is e.g. store everything lowercase. If you need both lowercase and case-preserving, you might need two maps; but, at this point, I'd consider requesting an interface change.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.