/ / Plantilla de sustitución de plantillas en función - c ++, plantillas

Sustitución de plantilla de plantilla en función - c ++, plantillas

Estoy implementando mi propio UniquePtr y me gustaría probar que tiene la misma interfaz que la std::unique_ptr. Así que escribí una función:

class A
{
A() { }
~A() { }
};

class B
{
B() { }
~B() { }
};


template <template <typename Type> class UPtr>
void test_unique_ptr_interface()
{
UPtr<A> p1(new A);
{
UPtr<A> p2(std::move(p1));
p1 = std::move(p2);
}

UPtr<B> p1(new B);
{
UPtr<B> p2(std::move(p1));
p1 = std::move(p2);
}
...
}

Y luego me gustaría llamarlo así:

test_unique_ptr_interface<std::unique_ptr>();
test_unique_ptr_interface<UniquePtr>();

La primera llamada prueba que la std::unique_ptr Pasa las pruebas, por lo que estoy probando la interfaz correcta. La segunda llamada pone a prueba mi propia UniquePtr La implementación funciona como una caída en el reemplazo. La función test_unique_ptr_interface Será mucho más largo, acabo de publicar un ejemplo simple.

Sin embargo, me sale un error:

error: no matching function for call to ‘test_unique_ptr_interface()’
test_unique_ptr_interface<std::unique_ptr>();

¿Cómo debo declarar el test_unique_ptr_interface() Funciona para que este compile?

Respuestas

5 para la respuesta № 1

Buscar el declaración de std::unique_ptr:

template <class T, class Deleter = std::default_delete<T>>
class unique_ptr;

Es una plantilla de clase con 2 parámetros de plantilla. Para copiarla exactamente, debe cambiar su plantilla de clase para que coincida, y cambiar la función de prueba:

template <template <typename, typename> class UPtr>
void test_unique_ptr_interface()
{
// ...
}

Una alternativa sería activar el parámetro variadic de la plantilla de plantilla:

template <template <typename... > class UPtr>
void test_unique_ptr_interface()
{
// ...
}

Esto permitiría a su clase mantener solo un parámetro de plantilla. Tenga en cuenta que no será un reemplazo completo para std::unique_ptr, aunque.


3 para la respuesta № 2

Cambia tu lista de argumentos de plantilla a:

template<template<class...>class UPtr>

como std::unique_ptr toma 2 argumentos, template<class>class no lo igualaré.

El hecho de que las plantillas coincidan en C ++ es un poco extraño (y no conozco la justificación), pero template<class...>class coincidirá con cualquier template class eso toma cero valores-parámetros (es decir, solo parámetros de tipo).

Ambos std::unique_ptr<?> (que toma 2 parámetros, 1 de ellos por defecto) y UniquePtr<?> (que toma 1 parámetro) coincidirá. Pasándolo un parámetro resultará en std::unique_ptr utilizando su segundo parámetro por defecto.

Es molesto que un template eso toma 2 parámetros, el segundo predeterminado, ganó "t" template<class>class, pero eso es parte de la forma "extraña" en que se combinan los parámetros de la plantilla. Podrías escribir un adaptador:

template<class T>using unique_ptr1 = std::unique_ptr<T>;

y pasar unique_ptr1 directamente a tu test_unique_ptr_interface.

Alternativamente:

template<template<class...>class Z>
struct unary_version {
template<class T>
using apply = Z<T>;
};

entonces

test_unique_ptr_interface< unary_version<std::unique_ptr>::template apply >

Es otra manera sin cambiar. test_unique_ptr_interface. Pero la respuesta correcta es reemplazar test_unique_ptr_interface.

Tenga en cuenta que su falta de eliminación significa que no coincide con el unique_ptr interfaz. En su lugar, podría aumentar su clase con esas características. Puede cambiar el nombre de su función existente para test_unique_ptr_interface_with_one_argy llamalo desde test_unique_ptr_interface que también prueba la funcionalidad deleter.


1 para la respuesta № 3

@Angew dio la respuesta correcta, aunque con su sugerencia específica tengo que cambiar UPtr<A> p1(new A); a UPtr<A, std::default_delete<A>> p1(new A);. Para evitar esto, necesito cambiar la declaración de función de

template <template <typename Type> class UPtr>
void test_unique_ptr_interface()

a

template <template <typename T, typename Deleter=std::default_delete<T>> class UPtr>
void test_unique_ptr_interface()

Entonces no son necesarios más cambios en el cuerpo de la función, todavía puedo usar UPtr<A> p1(new A); y todo lo compila.


0 para la respuesta № 4

std::unique_ptr toma dos parámetros de la plantilla (tipo y eliminador), por lo que su plantilla-plantilla también necesita tomar esos mismos dos parámetros.


-3 para la respuesta № 5

Utilizar solo (no es necesario template <typename Type>)

template <class UPtr>

Para la prueba puede usar std :: is_base_of con static_assert pero no sé cómo validar la clase de plantilla base