STL 关联容器:擦除并取回(不可复制的)元素
STL associative containers: erasing and getting back the (noncopyable) element
>我正在使用STL关联容器(std::set
和std::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++:从容器中删除元素并将其取回不起作用。
有没有非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;
}
这是其中之一:
真的很抱歉。 我们试图完成这项工作,但无法通过 委员会。
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
(并让移动构造函数修改对象)是 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
。
相关文章:
- 简单可复制与可简单复制
- 如何在 2d 矢量 c++ 中复制元素并将其放在原始元素旁边
- reinterpret_cast,只读访问,简单的可复制类型,会出什么问题?
- 对于参加可复制和可移动类的访问者来说,应该有多少过载?
- 可变参数宏:无法通过"..."传递非平凡可复制类型的对象
- 为什么 std::atomic<std::string> 会给出微不足道的可复制错误?
- 我可以隐式地创建一个琐碎的可复制类型吗
- std::tuple默认构造函数,带有move可构造元素
- r-在Rcpp和C++之间转换矢量(使用Rcpp::as或Rcpp:::wrap)是否会创建一个新的矢量并复制元素
- 是std::memcpy在不同的可复制类型之间的未定义行为
- 为什么一对常量是微不足道的可复制的,而对不是?
- 在一个微不足道的可复制结构中,移动语义应该实现吗?
- C 是否每次访问数组时都复制元素?
- 防止作用域枚举可复制/可移动
- C :对象上的可复制视图
- 防御性地应用 std::move 到平凡可复制的类型是否不可取
- 为什么 std::function 本身是可复制构造的类型?
- C++不可复制的 lambda 的行为是可复制的
- 错误:无法通过'...'传递非平凡可复制类型的对象'class boost::filesystem::path'
- 为什么向量中的元素需要是可复制的