关于自定义分配器和 stl 的模板声明、别名和专业化说明
Clarification in template declaration, alias and specialization in regards to custom allocators and stl
抱歉,标题含糊不清,但我不知道哪个是正确的术语(即使可以执行以下操作)。
假设我在某个地方有一个模板 class(一个分配器):
template<class Arena, typename T> Allocator
{
public:
Allocator(Arena a);
...
};
然后我有另一个class,它与Allocator
有某种关系,但不能在实例化时专门化T
参数。
这个想法是为它声明一个 "not specialized alias" ,并让专业化在其他地方。
类似于:
class MemoryArena
{
using Allocator<T> = AnAllocatorStrategy<T>; //not legal, but just to give the idea
void* Allocate(size_t);
};
用法应该是这样的:
Arena anArena(...);
Arena::Allocator<int> allocInt; // some way declare a specialization of the alias
std::vector<int, Arena::Allocator<int>> myVec(allocInt);
其背后的主要思想是,由于 stl
容器需要一个针对所包含元素类型的专用分配器,我仍然可以使用相同的内存空间并让专用实例将分配调用转发给它。
但我仍然希望 Arena 本身控制基本分配策略(最终还对未完全专门化的参数进行参数化 AllocatorStrategy
)。
有什么提示吗?这可能吗?
编辑
感谢评论,我以这种方式使用别名模板修复了声明:
class MemoryArena
{
template<typename T> using MyAllocatorTemplate = Allocator<MemoryArena, T>;;
void* Allocate(size_t);
};
我仍然需要弄清楚是否可以使 Allocator
成为 MemoryArena
定义的一部分,而无需完全指定 T
参数。类似于:
template<class AllocatorType<MemoryArena,?> = DefaultAllocType<MemoryArena,?>> //is possible not to specify T on MemoryArena definition?
class MemoryArena<AllocatorType>
{
template<typename T> using MyAllocatorTemplate = AllocatorType<MemoryArena,T>;
或者,您也可以提出任何其他建议。主要目标是让用户指定 Arena 的分配器类型,T
参数除外(仅对在容器内使用分配器有用)。
template<template<class...>class Z, class...T0s>
struct partial_apply {
template<class...T1s>
using result = Z<T0s...,T1s...>;
};
template<template<class...>class A, template<class...>class B>
struct same_template : std::false_type {};
template<template<class...>class A>
struct same_template<A,A> : std::true_type {};
template<class...>class Default {};
template<
template<class...>class AllocatorType=Default
>
class MemoryArena {
template<class T>
using MyAllocatorTemplate = std::conditional_t<
same_template<AllocatorType, Default>{},
DefaultAllocType<MemoryArena, T>,
AllocatorType<T>
>;
};
假设除了 DefaultAllocType
、OtherAllocType<Chicken, T>
之外还有其他分配类型。那么:
template<class...Ts>
using OtherAllocChicken = partial_apply<OtherAllocType, Chicken>::template result<Ts...>;
using ChickenArena = MemoryArena< OtherAllocChicken >;
另一方面,如果您要求传递给传入模板的参数是MemoryArena
本身有时,事情会变得更加复杂。
MemoryArena
参数化前,类型不存在。所以你必须有某种占位符可以告诉你应该在哪里注入它。
如果您希望它始终为 MemoryArena
,那么事情就更简单了:您已经有了该解决方案:
template<template<class...>class AllocatorType = DefaultAllocType>
class MemoryArena {
template<typename T>
using MyAllocatorTemplate = AllocatorType<MemoryArena,T>;
};
抱歉,标题含糊不清,但我不知道哪个是正确的术语(即使可以执行以下操作)。
假设我在某个地方有一个模板 class(一个分配器):
template<class Arena, typename T> Allocator
{
public:
Allocator(Arena a);
...
};
然后我有另一个class,它与Allocator
有某种关系,但不能在实例化时专门化T
参数。
这个想法是为它声明一个 "not specialized alias" ,并让专业化在其他地方。
类似于:
class MemoryArena
{
using Allocator<T> = AnAllocatorStrategy<T>; //not legal, but just to give the idea
void* Allocate(size_t);
};
用法应该是这样的:
Arena anArena(...);
Arena::Allocator<int> allocInt; // some way declare a specialization of the alias
std::vector<int, Arena::Allocator<int>> myVec(allocInt);
其背后的主要思想是,由于 stl
容器需要一个针对所包含元素类型的专用分配器,我仍然可以使用相同的内存空间并让专用实例将分配调用转发给它。
但我仍然希望 Arena 本身控制基本分配策略(最终还对未完全专门化的参数进行参数化 AllocatorStrategy
)。
有什么提示吗?这可能吗?
编辑
感谢评论,我以这种方式使用别名模板修复了声明:
class MemoryArena
{
template<typename T> using MyAllocatorTemplate = Allocator<MemoryArena, T>;;
void* Allocate(size_t);
};
我仍然需要弄清楚是否可以使 Allocator
成为 MemoryArena
定义的一部分,而无需完全指定 T
参数。类似于:
template<class AllocatorType<MemoryArena,?> = DefaultAllocType<MemoryArena,?>> //is possible not to specify T on MemoryArena definition?
class MemoryArena<AllocatorType>
{
template<typename T> using MyAllocatorTemplate = AllocatorType<MemoryArena,T>;
或者,您也可以提出任何其他建议。主要目标是让用户指定 Arena 的分配器类型,T
参数除外(仅对在容器内使用分配器有用)。
template<template<class...>class Z, class...T0s>
struct partial_apply {
template<class...T1s>
using result = Z<T0s...,T1s...>;
};
template<template<class...>class A, template<class...>class B>
struct same_template : std::false_type {};
template<template<class...>class A>
struct same_template<A,A> : std::true_type {};
template<class...>class Default {};
template<
template<class...>class AllocatorType=Default
>
class MemoryArena {
template<class T>
using MyAllocatorTemplate = std::conditional_t<
same_template<AllocatorType, Default>{},
DefaultAllocType<MemoryArena, T>,
AllocatorType<T>
>;
};
假设除了 DefaultAllocType
、OtherAllocType<Chicken, T>
之外还有其他分配类型。那么:
template<class...Ts>
using OtherAllocChicken = partial_apply<OtherAllocType, Chicken>::template result<Ts...>;
using ChickenArena = MemoryArena< OtherAllocChicken >;
另一方面,如果您要求传递给传入模板的参数是MemoryArena
本身有时,事情会变得更加复杂。
MemoryArena
参数化前,类型不存在。所以你必须有某种占位符可以告诉你应该在哪里注入它。
如果您希望它始终为 MemoryArena
,那么事情就更简单了:您已经有了该解决方案:
template<template<class...>class AllocatorType = DefaultAllocType>
class MemoryArena {
template<typename T>
using MyAllocatorTemplate = AllocatorType<MemoryArena,T>;
};