Template detects if T is pointer or class

会有一股神秘感。 提交于 2019-12-30 08:32:12

问题


Considering the following code:

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

How to tell the compiler call different methods based on if the template is a class or a pointer?

How to fix the code above?


回答1:


You can use a combination of std::is_pointer and 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;
}

Live example: https://ideone.com/CK8Zdo

This will allow you to insert both pointers and non-pointers into a pointer or non-pointer list. If you want to restrict that, you can use this:

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

Live example: https://ideone.com/3DtBfr




回答2:


I'm aware that my answer is not exactly about what you are asking, but maybe it could help.

I believe your intention is to have List class with one insert method (not two of them) and behaviour of this method should depend on your template parameter. For this you could write a specialization of your class for pointers. Then basic template would be used for non pointer types and specialization would be used for pointer types.

Your code would look like this:

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



回答3:


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

Inside List use a dispatcher

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

then dispatch to 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 }

Live example here. But, I'd encourage you to determine whether you really need that and possibly fix your design accordingly.




回答4:


This does the trick:

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

Here is a working example.



来源:https://stackoverflow.com/questions/30556176/template-detects-if-t-is-pointer-or-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!