8

Suppose I have a std::map<std::string, int>. Is there any way to use its at method with std::string_view? Here is a code snippet :

std::string_view key{ "a" };
std::map<std::string, int> tmp;
tmp["a"] = 0;
auto result = tmp.at(key);

Here is the output I have from clang 12.0

error: no matching member function for call to 'at'

auto result = tmp.at(key);

11
  • Hm, I get 'no matching member function to call at' using clang... Commented Feb 23, 2021 at 23:10
  • @Dmitry did you enable c++17 ? Commented Feb 23, 2021 at 23:10
  • Yes, even c++17 with cmake Commented Feb 23, 2021 at 23:12
  • 1
    @TonyTannous std::string_view was introduced in C++17 Commented Feb 23, 2021 at 23:13
  • Here is a demo. godbolt.org/z/Tn5jh1 .at is expecting std::string. That is why you are getting error. Just wrapped key with std::string. Commented Feb 23, 2021 at 23:14

2 Answers 2

9

Three things are required for something like this to happen:

  1. The map's comparator must be a transparent comparator (requires C++14, but you're already using string_view which is C++17, so this is a moot point).

  2. The at() method must have an overload that participates in overload resolution when the container has a transparent comparator.

  3. the parameter must be convertible to the map's key_type.

Neither of these are true in your example. The default std::less comparator is not a transparent comparator, there is no such overload for at(), and std::string does not have an implicit conversion from std::string_view.

There's nothing you can do about at(), however you can do something about the comparator namely using the (transparent std::void comparator), and then use find() instead of at(), which does have a suitable overload:

#include <map>
#include <string>
#include <string_view>


int main()
{
    std::string_view key{ "a" };
    std::map<std::string, int, std::less<void>> tmp;
    tmp["a"] = 0;

    auto iter=tmp.find(key);
}

More complete demo

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

Comments

3

There is no implicit conversion from std::string_view to std::string, that is why you get a "no matching member function" error. See: Why is there no implicit conversion from std::string_view to std::string?

There is a std::string constructor that will accept a std::string_view as input, however it is marked as explicit, so you will have to do this instead:

auto result = tmp.at(std::string(key));

Demo

Same if you wanted to use the map's operator[] with std::string_view:

tmp[std::string(key)] = ...;
auto result = tmp[std::string(key)];

1 Comment

Having to instantiate a string just for a lookup is so painful I'll always try to avoid that with all my forces

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.