【问题标题】:Transitivity guarantee for transparent comparisons in associative containers关联容器中透明比较的传递性保证
【发布时间】:2021-02-02 11:01:50
【问题描述】:

假设我们有一个带有自定义 Key 和传递比较器 Less 的有序容器,我们在其中进行查找,如下所示:

struct Key {
    int a, b;
    auto operator <=> (const Key&) const noexcept = default;
};

struct Less {
    bool operator ()(const Key& lhs, const Key& rhs) const noexcept {
        return lhs < rhs;
    }

    using is_transparent = void;
    bool operator ()(const Key& lhs, int rhs) const noexcept {
        return lhs.a < rhs;
    }
    bool operator ()(int lhs, const Key& rhs) const noexcept {
        return lhs < rhs.a;
    }
};

set<Key, Less> s = {{1, 1}, {1, 2}, {2, 1}, {2, 2}, {3, 1}, {3, 2}};
auto [begin, end] = s.equal_range(2);

现在的问题是:c++ 标准是否保证s.equal_range(2) 返回包含元素{2, 1}, {2, 2} 的范围,还是有一些基于传递性的UB?

换句话说:透明传递性的标准保证/要求与有序容器中关键传递性的保证/要求有什么不同吗?

【问题讨论】:

  • 确实,您的Less 不尊重严格的弱排序。 (2 &lt;=&gt; {2, 1}2 &lt;=&gt; {2, 2},但{2, 1} &lt; {2, 2})。
  • 按字典顺序按a, b 排序的元素显然仍按a 排序,所以如果这是一个排序向量,我会很好。但我实际上发现了这样一种情况,即透明度的差异与 libc++ 的std::map 的输出不同,所以我想知道这是否符合标准

标签: c++ c++-standard-library


【解决方案1】:

s.equal_range(ke) 被定义为等价于std::make_­pair( s.lower_­bound(ke), s.upper_­bound(ke));

std::set应该根据comp(x, ke)!comp(ke, x)(和c(x, ke)暗示!c(ke, x))进行分区。

有关正式要求,请参阅container.requirements#associative.reqmts.general-8

所以在你的情况下你是好的

{{1, 1}, {1, 2},   {2, 1}, {2, 2},   {3, 1}, {3, 2}}
//        x < 2  |    !(x < 2)
//                    !(2 < x)     |    2 < x
//

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-09-28
    • 2013-12-17
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多