提问人:Software Carpenter 提问时间:11/14/2022 最后编辑:Ken WhiteSoftware Carpenter 更新时间:11/14/2022 访问量:93
为什么 std::unordered_multiset<T> 的 == 运算符在 T 为指针类型时返回错误的结果?
Why does the == operator of std::unordered_multiset<T> returns wrong result when T is a pointer type?
问:
这是一个错误,还是我做错了什么?我已经尝试为指针类型提供哈希和相等函子,但它似乎不起作用。我甚至尝试创建自己的微型模板容器来测试函子。
哈希函子:
class CharPtHash
{
private:
using pChar = char*;
public:
size_t operator()(const pChar& c) const
{
std::hash<char> hasher;
if (c == nullptr)
{
return 0;
}
return hasher(*c);
}
};
平等:
class CharPtEqual
{
private:
using pChar = char*;
public:
bool operator()(const pChar& lhs, const pChar& rhs)const
{
if (lhs == rhs)//not sure of nullptr is equal to itself.
{
return true;
}
else if (lhs==nullptr || rhs==nullptr)
{
return false;
}
return *lhs == *rhs;
}
};
主要:
int main()
{
cout << "Testing unordered_multiset with keys being simple types:\n";
unordered_multiset<char> sA1({ 'a','b','c' });
unordered_multiset<char> sA2({ 'a','c','b' });
cout << "Values: " << endl << sA1 << endl << sA2 << endl;
cout << (sA1 == sA2 ? "Equal" : "Not Equal");
cout << endl;
cout << "Testing unordered_multiset with keys being pointers to simple types:\n";
char** c1 = new char* [3]{ new char('a'), new char('b'), new char('c') };
char** c2 = new char* [3]{ new char('a'), new char('c'), new char('b') };
unordered_multiset<char*,CharPtHash,CharPtEqual> sB1;
unordered_multiset<char*,CharPtHash,CharPtEqual> sB2;
sB1.insert(c1[0]);
sB1.insert(c1[1]);
sB1.insert(c1[2]);
sB2.insert(c2[0]);
sB2.insert(c2[1]);
sB2.insert(c2[2]);
cout << "Values: " << endl << sB1 << endl << sB2 << endl;
cout << (sB1 == sB2 ? "Equal" : "Not Equal");
cout << endl;
cin.get();
}
我尝试使用 Visual Studio 2022 将其编译为 c++20 和 c++14。
这是输出:
Testing unordered_multiset with keys being simple types:
Values:
{ a, b, c }
{ a, c, b }
Equal
Testing unordered_multiset with keys being pointers to simple types:
Values:
{ a, b, c }
{ a, c, b }
Not Equal
答:
好吧,我之前的回答是完全错误的:据我所知,你的和是正确的。但是,问题出在其他地方。运算符 ==
for 使用 std::is_permutation
() 在内部执行比较,并且不提供该算法的任何比较函数,因此使用该类型(在本例中)的默认值。我认为有 UB,但我不太明白那里的措辞。Hash
Pred
std::unordered_multiset
operator ==
char*
公平地说,这看起来像是标准的疏忽。 for 不允许比较不同类型的映射,因此应该可以将 instance 传递给 。或者也许有理由这样做,但我看不出来。operator ==
std::unordered_multimap
Pred
std::is_permutation
提供自己的只会在内部更改行为,即插入新项目。但是,它对 没有影响。KeyEqual
operator==
根据 operator==
(std::unordered_multiset
),它的行为就好像每个等价的 s 都与 进行了比较。equal_range
std::is_permutation
您可以潜在地针对 C++20 之前设置的行为进行专门化(这是自 C++20 以来未定义的行为):std::is_permutation
template<>
bool std::is_permutation(
std::unordered_multiset<char*, CharPtHash, CharPtEqual>::const_iterator l_begin,
std::unordered_multiset<char*, CharPtHash, CharPtEqual>::const_iterator l_end,
std::unordered_multiset<char*, CharPtHash, CharPtEqual>::const_iterator r_begin)
{
return std::is_permutation(l_begin, l_end, r_begin, CharPtEqual{});
}
或者只是使用自定义创建自己的包装器。char*
operator==
评论
new char('a')
new char('a')