Safe way to use string_view as key in unordered map

My type Val contains std::string thekey.

struct Val
{
std::string thekey;
float somedata;
}

I would like put my type in an unordered map, with thekey as key. For memory and conversion avoidance reasons I would like to have std::string_view as key type. Is it possible to have the key created to point to val.thekey, while using unique_ptr ?

std::unique_ptr<Val> valptr = ...;
std::unordered_map<std::string_view,std::unique_ptr<Val>> themap;
themap[std::string_view(valptr->thekey)] = std::move(valptr); // is this ok and safe?

Answer

Safe way to use string_view as key in unordered map

In general there isn’t one, because the storage underlying the view might change at any time, invalidating your map invariants.

Associative containers generally own a const key precisely to avoid this.

In your specific case it makes much more sense to use std::unordered_set<Val, ValKeyHash, ValKeyEqual> with suitable hash and equality functors.


Edit, these suitable functors are simply

struct ValKeyHash {
    std::size_t operator() (Val const &v)
    {
        return std::hash<std::string>{}(v.thekey);
    }
};

struct ValKeyEqual {
    bool operator() (Val const& a, Val const& b)
    {
        return a.thekey == b.thekey;
    }
};

Obviously this leaves us with the slightly unhappy requirement of using a temporary Val{key, dummy_data} for lookups, at least until we can use the C++20 transparent/projected version in the other answer.