微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

插入 std::set<std::tuple<std::string, ...>> 时重复

如何解决插入 std::set<std::tuple<std::string, ...>> 时重复

我尝试使用 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

解决方法

std::string::compare 返回 int(负,0,正)而不是 bool(小于),

你想要

std::get<0>(l).compare(std::get<0>(r)) < 0;

std::get<0>(l) < std::get<0>(r);
,

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 为 {{1} } 对于任何 truea,除非 b。特别是 a == ba < btrue 也被视为 b < a。这不符合 strict weak ordering 的要求并导致未定义的行为。您可以使用“普通”true 来比较字符串。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。