关于自定义分配器和 stl 的模板声明、别名和专用化的说明

Clarification in template declaration, alias and specialization in regards to custom allocators and stl

本文关键字:别名 专用 说明 声明 自定义 分配器 stl      更新时间:2023-10-16

很抱歉标题含糊不清,但我不知道哪个是正确的术语(即使可以执行以下操作)。

假设我在某处有一个模板类(分配器):

template<class Arena, typename T> Allocator
{
  public:
     Allocator(Arena a);
...
};

然后我还有另一个类,它与Allocator有某种关系,但不能专门化实例化T参数。这个想法是为它声明一个"非专用别名",并让专用化在其他地方。像这样:

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容器需要对所包含元素的类型进行专门的分配器,我仍然可以使用相同的内存领域,并让专用实例将分配调用转发给它。但我仍然希望竞技场本身控制基础分配策略(最终也参数化不完全专业化的AllocatorStrategy)。

对此有什么提示吗?这可能吗?


编辑

多亏了评论,我以这种方式使用别名模板修复了声明:

class MemoryArena
{
   template<typename T> using MyAllocatorTemplate = Allocator<MemoryArena, T>;;
  void* Allocate(size_t);
};

我仍然需要弄清楚是否可以在不完全指定T参数的情况下Allocator成为MemoryArena定义的一部分。像这样:

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>;

或者,欢迎任何其他建议。主要目标是让用户指定竞技场的分配器类型,但 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 之外还有其他一些 alloc 类型,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>;
};