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>; };
};
至于允许 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>
};
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 nameAllocator
is bound toSomeAllocator<T>
, thenAllocator::rebind<U>::other
is the same type asSomeAllocator<U>
, whereSomeAllocator<T>::value_type
isT
andSomeAllocator<U>:: value_type
isU
. — end note ] IfAllocator
is a class template instantiation of the formSomeAllocator<T, Args>
, whereArgs
is zero or more type arguments, andAllocator
does not supply arebind
member template, the standard allocator_traits template usesSomeAllocator<U, Args>
> in place ofAllocator:: 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>; };
};
至于允许 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>
};