std::allocator_traits 默认分配器有多个模板参数

std::allocator_traits defaults with allocator that has more than one template parameter

std::allocator_traits 当我提供一个带有单个模板参数的分配器的 STL 样式容器时,它会自动发挥它的魔力,但当我提供一个带有两个模板参数的分配器的 STL 样式容器时,它不会自动发挥作用模板参数,但在其他方面相似。

我需要做什么来告诉 std::allocator_traits 如何与具有多个模板参数的分配器交互?在这种情况下是否可以让 std::allocator_traits 提供合理的默认值?

例如,如果我采用 Howard Hinnant 在 Allocator Boilerplate 中提供的简单分配器并将其提供给 std::vector<>,那么一切都很好。如果我将虚拟 int 参数添加到 allocator 模板(并根据需要进行轻微修改),那么我会收到编译器错误,因为编译器找不到 rebind,等等。

这是代码中的描述:

http://coliru.stacked-crooked.com/a/173c57264137a351

如果我必须在这种情况下专门化 std::allocator_traits 自己,有没有办法仍然获得默认值?

标准仅为具有多个模板 type 参数的分配器提供默认值 rebind

17.6.3.5 Allocator requirements [allocator.requirements]

3 Note A: The member class template rebind in the table above is effectively a typedef template. [ Note: In general, if the name Allocator is bound to SomeAllocator<T>, then Allocator::rebind<U>::other is the same type as SomeAllocator<U>, where SomeAllocator<T>::value_type is T and SomeAllocator<U>:: value_type is U. — end note ] If Allocator is a class template instantiation of the form SomeAllocator<T, Args>, where Args is zero or more type arguments, and Allocator does not supply a rebind member template, the standard allocator_traits template uses SomeAllocator<U, Args> > in place of Allocator:: rebind<U>::other by default. For allocator types that are not template instantiations of the above form, no default is provided.

由于您有一个 non-type (int) 参数,因此没有提供默认值。修复很简单:只需将您自己的重新绑定添加到您的分配器。

template<class T, int I>
class allocator_w_int
{
    // as before

    template<class U>
    struct rebind { using other = allocator_w_int<U, I>; };    
};

Live Example

至于允许 Allocator<T, Args...> 形式的分配器但不允许 Alloc<T, Ns...> 形式的分配器的基本原理,只能猜测,但它也会导致过多的 Alloc<T, Args.., Ns...> 等等等等。这就是为什么 template-metaprogramming 库(例如 Boost.MPL)总是将类型 T 的 non-type 参数 N 包装在东西里面喜欢 integral_constant<T, N>。通过定义

,这也是您的路线
template<class T, class Arg>
class allocator_w_int; // leave undefined

template<int N>
using int_ = std::integral_constant<int, N>;

template<class T, int I>
class allocator_w_int<T, int_<I>>
{
    // replace all occurances of I, J --> int_<I>, int_<J>
};

Live Example