修改 std::D efined 行为的元素?

Modification of elements of std::Defined behavior?

本文关键字:元素 efined std 修改      更新时间:2023-10-16

给定以下代码:

#include <set>
struct X {
int a, b;
friend bool operator<(X const& lhs, X const& rhs) {
return lhs.a < rhs.a;
}
};
int main() {
std::set<X> xs;
// some insertion...
auto it = xs.find({0, 0}); // assume it != xs.end()
const_cast<X&>(*it).b = 4; // (1)
}

(1)定义的行为吗? 即,我是否可以const_cast对从std::setconst_iterator获得的元素的引用,并在修改不改变排序的情况下对其进行修改?

我在这里和那里阅读了一些提出这种const_cast的帖子,但我想知道这是否真的是定义的行为。

这是否定义了行为尚不清楚,但我相信确实如此。

std::set描述中似乎没有具体禁止修改值,除了您已经暗示的限制,即比较器在传递相同的输入时必须返回相同的结果([associaciative.reqmts]p3)。

但是,修改定义为const的对象的一般规则确实适用。set是否将其元素定义为const没有详细说明。如果是这样,则不允许修改元素 ([dcl.type.cv]p4)。

但是[container.requirements.general]p3写道:

对于受此子句影响的声明allocator_type的组件,存储在这些组件中的对象应使用allocator_traits<allocator_type>::construct函数和 使用allocator_traits<allocator_type>::destroy函数 (20.7.8.2) 销毁。

std::set<T>声明一个allocator_type,默认为std::allocator<T>std::allocator_traits<allocator_type>::construct传递它一个T *,导致构造一个T,而不是一个const T

我相信这意味着std::set<T>不允许将其元素定义为const,并且由于没有任何其他禁止,这意味着允许通过const_cast修改元素。


就个人而言,如果我找不到更好的选择,我会考虑通过将整个事情放在一个包装结构中来避免这个问题,该结构定义了成员mutable X x;。这将允许在没有const_cast的情况下进行修改,只要你注意避免改变集合中已有元素的相对顺序。此外,它还将作为代码的其他读者的文档,说明您的集合的元素可以并且将被修改。