#if __cplusplus >= 201103L template <class _Key,class _Tp> union __value_type { typedef _Key key_type; typedef _Tp mapped_type; typedef pair<const key_type,mapped_type> value_type; typedef pair<key_type,mapped_type> __nc_value_type; value_type __cc; __nc_value_type __nc; template <class ..._Args> _LIBCPP_INLINE_VISIBILITY __value_type(_Args&& ...__args) : __cc(std::forward<_Args>(__args)...) {} _LIBCPP_INLINE_VISIBILITY __value_type(const __value_type& __v) : __cc(__v.__cc) {} _LIBCPP_INLINE_VISIBILITY __value_type(__value_type& __v) : __cc(__v.__cc) {} _LIBCPP_INLINE_VISIBILITY __value_type(__value_type&& __v) : __nc(std::move(__v.__nc)) {} _LIBCPP_INLINE_VISIBILITY __value_type& operator=(const __value_type& __v) {__nc = __v.__cc; return *this;} _LIBCPP_INLINE_VISIBILITY __value_type& operator=(__value_type&& __v) {__nc = std::move(__v.__nc); return *this;} _LIBCPP_INLINE_VISIBILITY ~__value_type() {__cc.~value_type();} }; #else // definition for C++03...
看起来目的是使__value_type可分配和移动,同时还能够将内容公开为对< const key_type,mapped_type> (这是迭代器的值类型等).但我不明白为什么它需要可分配或可移动,因为我看不出任何理由为什么实现需要复制或移动地图内的节点,或者实际上做除了构造和销毁它们之外的任何事情-place,并重新配置指针.
解决方法
使用自定义分配器时,可能需要将映射(及其内容)移动到新的资源池中.在这种情况下,此重载将提供对键的可移动访问:
__value_type(__value_type&& __v) : __nc(std::move(__v.__nc)) {}
密钥已被移动并不重要,因为接下来发生的事情是释放所有节点.
请注意,此用法可能会导致未定义的行为.你通常不能写一个联盟的一个成员然后读另一个. Clang和libc可以做到这一点,只要他们可以在内部保证它不会导致问题(或错误诊断).
不过,他们可能就是这样做的,因为没有合适的替代品.至少,我想不出一个.该标准要求value_type :: first_type是真正的const限定的,所以即使是const_cast也是不允许的.
诀窍是在key_type和mapped_type都是标准布局的情况下符合,因此std :: pair< key_type,mapped_type>和std :: pair< key_type const,mapped_type>根据[class.mem]§9.2/ 16,布局兼容.这看起来有点奇怪,因为函数指的是union的直接成员__cc和__nc,将它留给构造函数来访问包含first和second的公共子序列.标准布局类型的requirements有些限制,但许多常见的键和值类型(例如,std :: string)可能会遇到它们.