插入 std::set<std::tuple<std::string, ...>> 时重复
Posted
技术标签:
【中文标题】插入 std::set<std::tuple<std::string, ...>> 时重复【英文标题】:Duplicates when inserting into std::set<std::tuple<std::string, ...>> 【发布时间】:2021-03-02 11:17:25 【问题描述】:我尝试使用 std::tuple 作为 std::set 的一个元素,其中 std 元组由 std::string 和一个 bool 组成(仅用于此示例,在正常使用情况下,元组由 3 个元素组成)。元组的字符串应该是唯一的,因此我创建了比较器,它将对元组的第一个元素上的元素进行排序。但是,当插入上述集合时,我确实在容器中得到了重复的元素。我看不出我在哪里犯了错误。提前感谢您的建议!
#include <set>
#include <functional>
#include <iostream>
using namespace std;
int main()
using tuple_t = std::tuple<std::string, bool>;
std::function<bool(const tuple_t &, const tuple_t &)> tupleCmp =
[](const tuple_t & l, const tuple_t & r) -> bool
return static_cast<bool>(std::get<0>(l).compare(std::get<0>(r)));
;
set<tuple_t, decltype(tupleCmp)> s(tupleCmp);
s.insert(make_tuple("ahoy", false));
s.insert(make_tuple("this", false));
s.insert(make_tuple("creates", false));
s.insert(make_tuple("duplicates", false));
s.insert(make_tuple("ahoy", false));
for (const auto & i : s)
cout << get<0>(i) << endl;
auto debug_stop = 0;
Debugger snippet
Output:
ahoy
duplicates
creates
this
ahoy
【问题讨论】:
我认为您的代码具有未定义的行为,因为tupleCmp
没有按照compare 的要求创建严格的弱排序。 std::set
的比较器不应该检查是否相等,而是暗示顺序。它的返回值必须指明是否为l < r
。
谢谢@churill,我一定误解了集合构造函数文档的“comp”。 return static_cast<bool>(std::get<0>(l)<(std::get<0>(r)));
工作。
【参考方案1】:
std::string::compare
返回int
(负,0,正)而不是bool
(小于),
你想要的
std::get<0>(l).compare(std::get<0>(r)) < 0;
或
std::get<0>(l) < std::get<0>(r);
【讨论】:
【参考方案2】:a.compare(b)
返回:
0 when the strings are equal
negative when a comes before b (ie a < b)
positive when b comes before a (ie b < a)
但是,比较器的返回值被转换为bool
,除0
之外的任何值都被转换为true
,因此您的比较器认为a < b
对于任何a
和b
都是true
除非a == b
。特别是a < b
是true
并且b < a
也被认为是true
。这不符合strict weak ordering 的要求,并导致未定义的行为。您可以使用“普通”<
来比较字符串。
【讨论】:
嗯,我的知识有差距。在测试它之前,我发誓 static_caststd::string::compare
模仿 Cs strcmp
并且在早期 C 没有 bool
。我猜如果 C++ 从一开始就进行三向比较std::string::compare
将不存在以上是关于插入 std::set<std::tuple<std::string, ...>> 时重复的主要内容,如果未能解决你的问题,请参考以下文章
std::set 插入器不尊重自定义比较器。 (可能的编译器错误?)
将 std::vector<std::tuple<>> 转换为 torch::Tensor 的最有效方法是啥?
创建 std::promise<std::tuple<T>> 时出现错误 C2512(仅限 Visual Studio)