template plantilla example curso con clases clase c++ templates segmentation-fault sfinae

plantilla - template typename t c++



La plantilla detecta si T es puntero o clase (4)

Esto hace el truco:

template <typename Object> class List { public: template<class C = Object> void insert(const C & x) { // call when Object is MyClass std::cout << "1" << "/n" ; } template<class P = Object*> void insert(P* p) { // call when Object is MyClass* std::cout << "2" << "/n" ; } } ;

Aquí hay un ejemplo de trabajo.

Teniendo en cuenta el siguiente código:

class MyClass { ... }; template <typename Object> class List { public: void insert(const Object & x) { // call when Object is MyClass } void insert(const Object & x) { // call when Object is MyClass* } } int main() { MyClass a; List<MyClass> lst; List<MyClass*> plst; lst.insert(a); plst.insert(new Myclass); return 0; }

¿Cómo decirle al compilador que invoque diferentes métodos según si la plantilla es una clase o un puntero?

¿Cómo arreglar el código de arriba?


Puede usar una combinación de std::is_pointer y std::enable_if :

#include <type_traits> #include <iostream> class MyClass { }; template <typename Object> class List { public: template<class T=Object> void insert(T t, typename std::enable_if<std::is_pointer<T>::value >::type* = 0) { std::cout << "insert pointer" << std::endl; } template<class T=Object> void insert(T t, typename std::enable_if<!std::is_pointer<T>::value >::type* = 0) { std::cout << "insert non-pointer" << std::endl; } }; int main() { MyClass a; List<MyClass> lst; List<MyClass*> plst; lst.insert(a); plst.insert(new MyClass()); return 0; }

Ejemplo en vivo: https://ideone.com/CK8Zdo

Esto le permitirá insertar punteros y no punteros en una lista de puntero o no puntero. Si quiere restringir eso, puede usar esto:

#include <type_traits> #include <iostream> class MyClass { }; template <typename Object> class List { public: template<class T=Object> void insert(T t, typename std::enable_if<std::is_same<T,Object>::value&&std::is_pointer<T>::value >::type* = 0) { std::cout << "insert pointer" << std::endl; } template<class T=Object> void insert(const T& t, typename std::enable_if<std::is_same<T,Object>::value&&!std::is_pointer<T>::value >::type* = 0) { std::cout << "insert non-pointer" << std::endl; } }; int main() { MyClass a; List<MyClass> lst; List<MyClass*> plst; lst.insert(a); // plst.insert(a); // compiler error // lst.insert(new MyClass()); // compiler error plst.insert(new MyClass()); return 0; }

Ejemplo en vivo: https://ideone.com/3DtBfr


Soy consciente de que mi respuesta no es exactamente sobre lo que estás preguntando, pero quizás podría ser útil.

Creo que su intención es tener la clase List con un método insert (no dos de ellos) y el comportamiento de este método dependerá de su parámetro de plantilla. Para esto podrías escribir una especialización de tu clase para punteros. Entonces la plantilla básica se usaría para tipos que no sean de puntero y se usaría especialización para los tipos de puntero.

Tu código se vería así:

template <typename Object> class List { public: void insert(const Object & x) { // call when Object is MyClass } }; template <typename Object> class List<Object *> { public: void insert(Object * x) { // call when Object is MyClass* } };


void insert(const Object & x) { M_insert(x, dispatcher<std::is_pointer<Object>::value> ); }

List interna usa un despachador

template <bool B> class dispatcher {}; using ObjectPtr = dispatcher<true>; using ObjectValue = dispatcher<false>;

luego M_insert a M_insert :

void M_insert(const Object &p, ObjectPtr) { // Object is a pointer } void M_insert(const Object &p, ObjectValue) { // Object is not a pointer }

Ejemplo en vivo aquí . Pero, lo animo a que determine si realmente lo necesita y posiblemente arregle su diseño en consecuencia.