Bonita Montero wrote:
> Am 07.09.2023 um 05:54 schrieb Pavel:
>
>>> In theory there might be overloaded specializations that take
>>> a string_view or whatever;
>
>> not needed
>
> With out such a specialization a string object needs to be created
> inside find to have compatible hashing and equality comparison.
Not true. I was benevolently trying to make you read the standard so you
could become a better C++ programmer but you refused.
I am therefore giving up on helping you. I will become evil and post the
complete standard-compliant example that demonstrates how exactly the
unordered_map::find can be made work on string literal and the map with
the string keys without creating a string object (in the example, the
string is wrapped in StringKey to track constructions easily but you are
welcome to remove the wrapper). The code will work as described under
C++20 but not any previous version of the standard -- and this is the
expected behavior.
You still have a chance to improve your C++ programming skills if you
read the standard and find the explanation for why this code shall
behave like it does.
// ------------- code begin cut here -------------------------
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <numeric>
#include <string>
#include <unordered_map>
using namespace std;
class StringKey {like
public:
StringKey(const char* cStr): s_(cStr) {
cout << "\n\t(StringKey(" << cStr << ") called)\n";
}
const string& getS() const { return s_; }
private:
string s_;
};
struct StringKeyHash {
typedef void is_transparent;
size_t operator()(const char *s) const {
assert(!!s);
return Hash(s, s + strlen(s));
}
size_t operator()(const StringKey &s) const {
return Hash(s.getS().data(), s.getS().data() + s.getS().size());
}
private:
static size_t Hash(const char* begin, const char* end) {
return accumulate(begin, end, (size_t) 0u,
[](size_t a, char c) -> size_t { return a + (size_t)c; });
}
};
struct StringKeyEq {
typedef void is_transparent;
bool operator()(const StringKey& x, const StringKey& y) const {
return IsEq(x.getS().c_str(), y.getS().c_str());
}
bool operator()(const StringKey& x, const char* y) const {
assert(!!y);
return IsEq(x.getS().c_str(), y);
}
bool operator()(const char* x, const StringKey& y) const {
assert(!!x);
return IsEq(x, y.getS().c_str());
}
private:
static bool IsEq(const char *x, const char *y) {
assert(!!x);
assert(!!y);
for (;; ++x, ++y) {
if (*x == *y) {
if (!*x)
return true;
continue;
}
assert(*x != *y);
return false;
}
}
};
int
main(int, char*[]) {
cout << "*** fill up the unordered map\n";
unordered_map<StringKey, string, StringKeyHash, StringKeyEq> um {
{ "key1", "val1" },
{ "key2", "val2" },
};
const char* key3 = "key3";
const char* key4 = "key4";
const char* key1 = "key1";
cout << "*** now do the the find\n";
const auto i1 = um.find(key1);
const bool r1 = i1 == um.end();
const auto i3 = um.find(key3);
const bool r3 = i3 == um.end();
const auto i4 = um.find(key4);
const bool r4 = i4 == um.end();
cout << "find(" << key1 << "):" << r1 << ' ' <<
"find(" << key4 << "):" << r4 << ' ' <<
"find(" << key3 << "):" << r3 << endl;
return 0;
}
// ------------- code end cut here -------------------------
// --- example run output if compiled by g++ -std=c++20 begin ---
$ ./a.out
*** fill up the unordered map
(StringKey(key1) called)
(StringKey(key2) called)
*** now do the the find
find(key1):0 find(key4):1 find(key3):1
// --- example run output if compiled by g++ -std=c++20 end ---
// --- example run output if compiled by g++ -std=c++17 begin ---
$ ./a.out
*** fill up the unordered map
(StringKey(key1) called)
(StringKey(key2) called)
*** now do the the find
(StringKey(key1) called)
(StringKey(key3) called)
(StringKey(key4) called)
find(key1):0 find(key4):1 find(key3):1
// --- example run output if compiled by g++ -std=c++17 end ---
>
>>> but that's ratther unlikely.
>
>> close but imprecise. That's simply not there.
>
> That's a theoretically valid possibility,
> so it can't be said that it doesn't exist.
This is "theoretically valid" only for those who refuse to read the
standard; the others know the specialization is not there.