【发布时间】:2018-10-09 09:05:51
【问题描述】:
考虑以下虚拟分配器(为示例而创建):
template<typename T> class C
{
public:
typedef T value_type;
C() = default;
template<typename U>
C(C<U> const &a)
{}
T* allocate(std::size_t n, T const* = nullptr)
{
return new T[n];
}
void deallocate(T* p, std::size_t n)
{
return;
}
typedef value_type *pointer;
typedef const value_type *const_pointer;
typedef value_type & reference;
typedef value_type const &const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static pointer address(reference x) { return &x; }
static const_pointer address(const_reference x) { return &x; }
static size_type max_size() { return std::numeric_limits<size_type>::max(); }
template <typename U> static void destroy(U* ptr) { ptr->~U(); }
template <typename U> struct rebind { using other = C<U>; };
template<typename U, typename... Args>
static void construct(U* ptr, Args&&... args) {
new (ptr) U(std::forward<Args>(args)...);
}
};
template<class T1, class T2>
bool operator==(C<T1> const& lhs, C<T2> const& rhs)
{
return std::addressof(lhs) == std::addressof(rhs);
}
template<class T1, class T2>
bool operator!=(C<T1> const& lhs, C<T2> const& rhs)
{
return !(lhs == rhs);
}
大部分代码都是样板代码。关键的细节是分配器的任何两个实例都将被认为是不兼容的——bool operator== 总是返回false。当我尝试将此分配器与大多数 STL 容器(例如 std::vector)一起使用来复制分配非常简单的元素时,例如:
std::vector<int, C<int>> a;
a = std::vector<int, C<int>>();
一切正常,我得到了预期的行为。但是,当我做同样的事情,但使用std::unordered_map 时,我在需要支持的两个平台上得到不同的行为。在带有 GCC 7.1 的 Linux 上,我继续得到预期的行为。然而,在带有 VS 2015 的 Windows 上,我在标题为 xmemory0 的 VS 标头中收到声明失败的声明 containers incompatible for swap。请注意,用于std::unordered_map 的代码与上面用于std::vector 的代码几乎相同:
using B = std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, C<std::pair<int const, int>>>;
B b;
b = B();
我的分配器是否存在固有问题,而 GCC 7.1 给了我未定义的行为?如果不是,这是 VS 2015 运行时库的故障吗?如果是这样,为什么这个故障只出现在unordered_map?
【问题讨论】:
标签: c++ unordered-map allocator