2

Suppose I have a private std::map inside my class std::map<std::string, double>. How can I transform is to std::map<std::string_view, double> to return to the user? I'd like to have the following prototype here

const std::map<std::string_view, double>&
MyClass::GetInternalMap() const;
3
  • 3
    What's the motivation? Returning a const& is already effectively a "view". None of the underlying memory will be copied. Commented Feb 23, 2021 at 21:23
  • @0x5453 For the moment I’m doing a clean-up for my code to optimize the performance, and that was a question for me how to do it in a better way. This exact example is just an illustration for my intention Commented Feb 23, 2021 at 21:31
  • 1
    There's a big difference: string is owning and string_view not. So they're not the same. Commented Feb 23, 2021 at 21:44

1 Answer 1

5

You should not return the new map by const reference. You would be returning a dangling reference to a temp map that was destroyed when GetInternalMap() exits. If you want to return a const reference, then you should return the source map as-is, eg:

const std::map<std::string, double>& MyClass::GetInternalMap() const
{
    return myvalues;
}

Otherwise, return the new map by value instead:

std::map<std::string_view, double> MyClass::GetInternalMap() const;

That being said, a std::map<std::string,double> is not directly convertible to a std::map<std::string_view,double>, so you would have to manually iterate the source map one element at a time, assigning each one to the target map, eg:

std::map<std::string_view, double> MyClass::GetInternalMap() const
{
    std::map<std::string_view, double> result;
    for(auto &p : myvalues) {
        result[p.first] = p.second;
        // or: result.emplace(p.first, p.second);
    }
    return result;
}

Fortunately, a std::pair<std::string,double> is implicitly convertible to a std::pair<std::string_view,double>, so you could simply use the map constructor that takes an iterator range as input, and let map assign the elements for you, eg:

std::map<std::string_view, double> MyClass::GetInternalMap() const
{
    return {myvalues.begin(), myvalues.end()};
}
Sign up to request clarification or add additional context in comments.

2 Comments

thanks a lot for a quick answer ! I was looking for any kind of stl solution here but nevertheless your approach is fine for me also
I think you can construct the result map directly using the two-iterator constructor. I tested GCC, Clang, and MSVC; they all accepted return { begin(myvalues), end(myvalues) }; as the entire function body.

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.