std :: set元素的修改 - 定义的行为?

时间:2017-04-11 08:01:45

标签: c++ set const-cast

给出以下代码:

#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引用从const_iterator std::set获取的元素,如果修改不改变顺序,则修改它?

我已经阅读了一些帖子,提出了这种const_cast,但我想知道这是否是实际定义的行为。

1 个答案:

答案 0 :(得分:2)

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

std::set关于修改值的描述中似乎没有明确的禁止,除了你已经暗示的限制,比较器在传递相同的输入时必须返回相同的结果([associative.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>::constructT *传递给T,导致构建const T,而不是std::set<T>

我认为这意味着const不允许将其元素定义为const_cast,并且由于没有任何其他禁止,意味着允许通过mutable X x;修改元素。

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