C++ 自定义分配器:const_pointer 'has not been declared'

C++ custom allocator: const_pointer 'has not been declared'

我在为自定义分配器编写自定义 'allocate' 方法时遇到问题。根据 cppreference 此方法的签名如下:

pointer allocate( size_type n, std::allocator<void>::const_pointer hint = 0 );

然而,当我为我的分配器定义这个方法时,我从编译器收到消息“'const_pointer' 尚未声明”。下面是显示问题的精简代码。

template <class T>
class linear_allocator
{
public:
    typedef T* pointer;
    typedef const T* const_pointer;

    linear_allocator() {}
    ~linear_allocator() {}

    pointer allocate(unsigned int n, 
                    linear_allocator<void>::const_pointer hint = 0)
    {
      return 0;
    }
};

int main()
{
  linear_allocator<double> test_allocator;
}

一定是我遗漏了一些简单的东西,但是什么?

问题是由 linear_allocator<void> class 模板在自身内部的显式实例化引起的。您可能应该将其设为单独的非模板基础 class。

如果你正在处理 C++17,那么你可以简单地编写这个函数来匹配新规范:

pointer allocate(std::size_t n)

您可以在分配器中为 void_pointerconst_void_pointer 显式提供别名。 Allocator is that the parameter matches allocator_traits<Alloc>::const_void_pointer 中的(可选)要求是

Alloc::const_void_pointer if present, otherwise std::pointer_traits<pointer>::rebind<const void>

清理完毕,得到

template <class T>
class linear_allocator
{
public:
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef void* void_pointer;
    typedef const void* const_void_pointer;
    typedef unsigned int size_type;

    linear_allocator() {}
    ~linear_allocator() {}

    pointer allocate(size_type n, const_void_pointer hint = nullptr)
    {
      return 0;
    }
};

我研究了 stl::allocator 实施(应该从头开始)。正如 VTT 用户指出的那样,问题是由 linear_allocator<void> 内部的显式实例化引起的。我自己也一样,但对方法定义看起来好像应该有效感到困惑 'as it is'。

显然有很多方法可以解决这个问题——最简单的就是使用 const void* 作为 hint 的类型。我很想知道为什么它适用于标准 stl::allocator 而不是我的情况。

所以,在研究了这里的实现之后,就是解决方案:

  1. 声明模板化 class 'linear_allocator'.
  2. 使用明确的模板名称 <void> 定义 class linear_allocator -- 我们只需要部分定义 class -- 只需输入我们将要使用的类型。
  3. 为通用模板 class 名称定义 linear_allocator

工作代码如下:

template <typename T>
class linear_allocator;

template <>
class linear_allocator<void>
{
public:
    typedef void* pointer;
    typedef const void* const_pointer;
};

template <class T>
class linear_allocator
{
public:
    typedef T* pointer;
    typedef const T* const_pointer;

    linear_allocator() {}
    ~linear_allocator() {}

    pointer allocate(unsigned int n, 
                     linear_allocator<void>::const_pointer hint = 0)
    {
      return 0;
    }
};
int main()
{
  linear_allocator<double> test_allocator;
}