STL关联容器:删除和获取(不可复制)元素

5

我正在使用STL关联容器 (std::setstd::map),并且键值是一个包含std::unique_ptr<>实例的对象。键值定义等价于以下内容:

struct Key
{
    std::unique_ptr<Object> object;
    bool operator== (const Key& rhs) const { return object->equal (*rhs.object); }
    bool operator<  (const Key& rhs) const { return object->less (*rhs.object); }
}

众所周知,STL关联容器(特别是自C++11以来)没有一种方法可以获得非常量引用以从中移动键。而我的键是不可复制的,因此c++: Remove element from container and get it back无法使用。
是否有一种非UB的方法来解决这个问题?
我目前的解决方案如下:
template <typename T>
using map_pair_type = std::pair<typename T::key_type, typename T::mapped_type>;

template <typename T>
typename T::value_type take_set (T& container, typename T::iterator iterator)
{
    typename T::value_type result = std::move (const_cast<typename T::value_type&> (*iterator));
    container.erase (iterator);
    return result;
}

template <typename T>
map_pair_type<T> take_map (T& container, typename T::iterator iterator)
{
    map_pair_type<T> result {
        std::move (const_cast<typename T::key_type&> (iterator->first)),
        std::move (iterator->second)
    };
    container.erase (iterator);
    return result;
}

3
有没有一种非 UB 的方法来解决这个问题?不行。N3645 可能有所帮助,但是该提案被拒绝并且没有重新提交。 - Jonathan Wakely
1个回答

7

这是其中之一:

非常抱歉。我们尝试过让它发挥作用,但无法通过委员会审核。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3586.pdf

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3645.pdf

据我所知,您的解决方案是最好的。您的映射解决方案存在未定义行为。如果第二个移动操作引发异常,情况将变得非常糟糕。除此之外,我认为它能够正常工作。我怀疑我会因为这样的说法而遭到贬低。

UB的原因是键被定义为const(而不仅仅是由const引用引用)。在这种情况下强制转换const(并使移动构造函数修改对象)是UB。

如果N3586被接受,您可以直接执行以下操作:

move_only_type mot = move(*s.remove(s.begin()));

或者:

move_only_key mok = move(m.remove(m.begin())->first);

N3586 / N3645在委员会中表现不错。经过讨论并通过工作组阶段,但是却在全体委员会中被否决了。问题在于std::lib必须提交UB才能实现它。尚未重新提交。

更新

现在在C ++ 17中可以这样做,但成员函数称为extract而不是remove


感谢你的回答。如果我成功地使用异常安全(比如 RAII 风格的迭代器“擦除器”),它是否仍然会存在未定义行为? - intelfx
还有一个后续问题。那个提案的状态是什么?被拒绝了,还是还没有审核,或者被拒绝并将重新提交? - intelfx
1
强制转换掉 const 永远不会导致未定义行为。试图修改 const 对象是未定义行为。 - Columbo
@Columbo:从一个对象移动并不算修改它吗?不过你说得对,这个答案的措辞在这方面可能有点误导性。 - Lightness Races in Orbit
公正的观点。我已经尝试让答案更准确了。 - Howard Hinnant
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接