Tengo un problema al escribir el método personalizado 'asignar' para el asignador personalizado. Según cppreference la firma de este método es la siguiente:

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

Sin embargo, cuando defino este método para mi asignador, recibí el mensaje del compilador "'const_pointer' no ha sido declarado". A continuación se muestra el código reducido que muestra el problema.

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

Debe ser algo simple que me estoy perdiendo, pero ¿qué?

2
one_two_three 16 ene. 2018 a las 14:07

3 respuestas

La mejor respuesta

He examinado la implementación de stl :: allocator (debería hacerlo desde el principio). El problema, como señaló el usuario de VTT, fue causado por la instanciación explícita de linear_allocator<void> dentro de sí mismo. Pensé tanto en mí mismo, pero estaba confundido de que la definición del método parece funcionar 'tal como está'.

Obviamente, hay muchas formas de solucionar este problema: la más simple sería usar const void* como tipo para hint. Estaba interesado en entender por qué funcionó para el estándar stl::allocator y no en mi caso.

Entonces, después de analizar la implementación, aquí está la solución:

  1. Declare la clase con plantilla 'linear_allocator'.
  2. Defina la clase linear_allocator con el nombre explícito de la plantilla <void>: solo necesitamos una definición parcial de esta clase, solo escriba el que vamos a utilizar.
  3. Defina linear_allocator para el nombre genérico de la clase de plantilla.

El código de trabajo está abajo:

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;
}
0
one_two_three 16 ene. 2018 a las 14:38

Puede proporcionar explícitamente un alias para void_pointer y const_void_pointer en su asignador. El requisito (opcional) en Allocator es que el parámetro coincide con allocator_traits<Alloc>::const_void_pointer, que es

Alloc::const_void_pointer si está presente, de lo contrario std::pointer_traits<pointer>::rebind<const void>

Limpiada, obtienes

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;
    }
};
0
Caleth 16 ene. 2018 a las 11:51

El problema es causado por la instanciación explícita de la plantilla de clase linear_allocator<void> dentro de sí misma. Probablemente deberías convertirlo en una clase base separada sin plantilla.

Si se trata de C ++ 17, simplemente puede escribir esta función para que coincida con las nuevas especificaciones:

pointer allocate(std::size_t n)
2
user7860670 16 ene. 2018 a las 11:13