Template detects if T is pointer or class

后端 未结 4 498
[愿得一人]
[愿得一人] 2020-12-19 04:27

Considering the following code:

class MyClass
{
    ...
};

template 
class List
{
public:

    void insert(const Object & x)
             


        
相关标签:
4条回答
  • 2020-12-19 04:37

    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*
        }
    };
    
    0 讨论(0)
  • 2020-12-19 04:46

    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

    0 讨论(0)
  • 2020-12-19 04:52

    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.

    0 讨论(0)
  • 2020-12-19 04:58
    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.

    0 讨论(0)
提交回复
热议问题