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 № 1Buscar 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_arg
y 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