MSVC C++17 (2019) 上的 Operator() 崩溃程序
Operator() crashing program on MSVC C++17 (2019)
以下代码不适用于 MSVC++ 2019,但适用于 GCC 编译器。
#include <set>
#include <string>
#include <iostream>
struct MyData {
MyData() {}
MyData(std::string keyA, std::string keyB) :keyA(keyA), keyB(keyB) {}
std::string keyA;
std::string keyB;
};
struct Compare {
bool operator() (const MyData& lhs, const MyData& rhs) const
{
if (lhs.keyA < rhs.keyA)
return true;
if (lhs.keyB < rhs.keyB)
return true;
else
// All else conditions would be false
return false;
}
};
int main()
{
std::set<MyData, Compare> s;
s.insert(MyData("Clark", "Alice"));
s.insert(MyData("Bob", "Alice"));
s.insert(MyData("Alice", "Bob"));
s.insert(MyData("Derek", "Clark"));
for (auto& i : s)
{
std::cout << i.keyA << ", " << i.keyB << std::endl;
}
}
这是 MSVC 上的错误:
在 GCC 上,它显示以下输出:
Alice, Bob
Bob, Alice
Clark, Alice
Derek, Clark
Process returned 0 (0x0) execution time : 0.971 s
Press any key to continue.
是什么导致了这个错误,如何正确定义运算符?
您的比较对象不符合strict weak ordering的规则,即可能出现以下情况:
a < b
b < c
a >= c
MSVC 显然已经检测到这一点并引发断言失败。
要解决此问题,您可以按如下方式更改比较器:
bool operator() (const MyData& lhs, const MyData& rhs) const
{
if (lhs.keyA < rhs.keyA)
return true;
if (lhs.keyA == rhs.keyA && lhs.keyB < rhs.keyB)
return true;
return false;
}
或者更简洁地使用 std::tie
:
bool operator() (const MyData& lhs, const MyData& rhs) const
{
return std::tie (lhs.keyA, lhs.keyB) < std::tie (rhs.keyA, rhs.keyB);
}
我也去掉了多余的else
。
Compare::operator()
不正确。不符合strict weak ordering.
的条件
您可以将其更改为:
bool operator() (const MyData& lhs, const MyData& rhs) const
{
if (lhs.keyA != rhs.keyA)
return (lhs.keyA < rhs.keyA)
return (lhs.keyB < rhs.keyB);
}
可以使用std::tie
进一步简化。
bool operator() (const MyData& lhs, const MyData& rhs) const
{
return std::tie(lhs.keyA, lhs.keyB) < std::tie(rhs.keyA, rhs.keyB);
}
以下代码不适用于 MSVC++ 2019,但适用于 GCC 编译器。
#include <set>
#include <string>
#include <iostream>
struct MyData {
MyData() {}
MyData(std::string keyA, std::string keyB) :keyA(keyA), keyB(keyB) {}
std::string keyA;
std::string keyB;
};
struct Compare {
bool operator() (const MyData& lhs, const MyData& rhs) const
{
if (lhs.keyA < rhs.keyA)
return true;
if (lhs.keyB < rhs.keyB)
return true;
else
// All else conditions would be false
return false;
}
};
int main()
{
std::set<MyData, Compare> s;
s.insert(MyData("Clark", "Alice"));
s.insert(MyData("Bob", "Alice"));
s.insert(MyData("Alice", "Bob"));
s.insert(MyData("Derek", "Clark"));
for (auto& i : s)
{
std::cout << i.keyA << ", " << i.keyB << std::endl;
}
}
这是 MSVC 上的错误:
在 GCC 上,它显示以下输出:
Alice, Bob
Bob, Alice
Clark, Alice
Derek, Clark
Process returned 0 (0x0) execution time : 0.971 s
Press any key to continue.
是什么导致了这个错误,如何正确定义运算符?
您的比较对象不符合strict weak ordering的规则,即可能出现以下情况:
a < b
b < c
a >= c
MSVC 显然已经检测到这一点并引发断言失败。
要解决此问题,您可以按如下方式更改比较器:
bool operator() (const MyData& lhs, const MyData& rhs) const
{
if (lhs.keyA < rhs.keyA)
return true;
if (lhs.keyA == rhs.keyA && lhs.keyB < rhs.keyB)
return true;
return false;
}
或者更简洁地使用 std::tie
:
bool operator() (const MyData& lhs, const MyData& rhs) const
{
return std::tie (lhs.keyA, lhs.keyB) < std::tie (rhs.keyA, rhs.keyB);
}
我也去掉了多余的else
。
Compare::operator()
不正确。不符合strict weak ordering.
您可以将其更改为:
bool operator() (const MyData& lhs, const MyData& rhs) const
{
if (lhs.keyA != rhs.keyA)
return (lhs.keyA < rhs.keyA)
return (lhs.keyB < rhs.keyB);
}
可以使用std::tie
进一步简化。
bool operator() (const MyData& lhs, const MyData& rhs) const
{
return std::tie(lhs.keyA, lhs.keyB) < std::tie(rhs.keyA, rhs.keyB);
}