Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::map not always allow a compatible type as its key type?

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

using namespace std;

int main()
{
    string_view key = "hello";      
    map<string, int, less<>> coll;
    coll.find(key); // ok
    coll[key] = 0;  // !!! error ???
}

The key type is std::string, the compatible type is std::string_view. Since C++14, std::map::find allows a compatible key to be used; so coll.find(key); is ok.

However, why isn't coll[key] = 0; ok too?

like image 411
xmllmx Avatar asked Dec 18 '25 13:12

xmllmx


2 Answers

coll.find(key) only requires key to be comparable with the actual key type, and std::string_view is comparable with std::string. However, in order to be able to insert key into coll, key needs to be convertible to std::string, which it is not (implicitly, anyway).

like image 199
Brian Bi Avatar answered Dec 21 '25 04:12

Brian Bi


The rationale behind was described in N3465.

Conceptually, the extension consists in replacing the original formulation based on strict weak orderings with one relying on the notion of sequence partitioning, as first proposed by David Abrahams. Unfortunately, this extension process has not been carried out for the lookup operations of associative containers, which are still formulated in terms of strict weak orderings and thus do not allow for heterogeneous comparison.

Take this example from N3465, and modify its a bit:

struct name_entry
{
    std::string family_name;
    std::string given_name;
};
auto as_tuple(const name_entry& e)
{
     return std::tie(e.family_name, e.given_name);
}
bool operator<(const name_entry& x, const name_entry& y)
{
    return as_tuple(x) < as_tuple(y);
}
bool operator<(const name_entry& x, const std::string& y) 
{
    return x.family_name<y;
}
bool operator<(const std::string& x, const name_entry& y) 
{
    return x<y.family_name;
}
int main()
{
    std::set<name_entry, std::less<>> names;
} 

Heterogeneous comparison was invented to duel with find the contained object that satisfied partial comparison like find someone has a given surname.

operator[], in other hand, will construct a value_type if the key is not found, it's necessary to apply strict weak ordering with this operation, thus cannt be applied with heterogeneous comparison

like image 39
Danh Avatar answered Dec 21 '25 05:12

Danh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!