指针重新绑定的目的是什么?

What is the purpose of pointer rebind?

我正在尝试实施 std::list (MSVC)。还有一件事我无法理解:

template <class _Value_type, class _Voidptr> // voidptr? For what?
struct _List_node { // list node
    using value_type = _Value_type;
    using _Nodeptr   = _Rebind_pointer_t<_Voidptr, _List_node>; // what is the purpose of such rebind?
    ...
}

我明白分配器重新绑定的原因,但是指针?我为什么要使用它以及在哪里使用它?

UPD:我明白了,什么是重新绑定。我的意思是,为什么不只是 _Nodeptr*?为什么我需要重新绑定? (感谢 Evg)

用户使用 value_type. 实例化列表 例如,对于 list<int>value_type 将是 int。 此外,列表分配器(也可以提供)为 value_type 的对象分配内存。

但是 value_type 不是 列表内部包含的内容。 该列表内部包含 **Nodes**,value_type 是其成员。

因此,为了能够将分配和指针从 value_type 转换为 Node(至少包含 value_type 和指向下一个节点的指针),使用了重新绑定。

相反,例如 vector<int> 则不需要。 这是因为 vector 的内部表示通常会在内部保存指向 value_type 对象数组的指针,在本例中是 int。所以这里不需要重新绑定。

这个问题的答案也来自分配器。我们来看看 _Rebind_pointer_t 是如何 defined:

template <class _Ptr, class _Ty>
using _Rebind_pointer_t = typename pointer_traits<_Ptr>::template rebind<_Ty>;

也就是说,我们有

template <class _Value_type, class _Voidptr>
struct _List_node {
    using _Nodeptr = typename pointer_traits<_Voidptr>::template rebind<_List_node>;
    // ...
}

现在让我们来看看_List_node是如何used:

using _Node = _List_node<_Ty, typename _Alty_traits::void_pointer>;

实际上,我们将分配器的 void_pointer 重新绑定到 _List_node 指针。需要这个技巧来支持在内部使用奇特指针的分配器。


可以在 Boost.Interprocess 库中找到一个这样的例子。它有 boost::interprocess::allocator:

An STL compatible allocator that uses a segment manager as memory source. The internal pointer type will of the same type (raw, smart) as typename SegmentManager::void_pointer type. This allows placing the allocator in shared memory, memory mapped-files, etc...

比如我们可以这样写

namespace bi = boost::interprocess;
using Allocator = bi::allocator<int, bi::managed_shared_memory::segment_manager>;
std::list<int, Allocator> list(/* allocator object */);

现在 std::allocator_traits<decltype(list)::allocator_type>::void_pointer 将不是默认分配器的 void*,而是 boost::interprocess::offset_ptr<void, ...>。结果,_Nodeptr 将不是 _Nodeptr*,而是 boost::interprocess::offset_ptr<_Nodeptr, ...>