Have a template parameter that can be pointer type or non-pointer type

后端 未结 3 1147
北海茫月
北海茫月 2021-01-17 16:38

Suppose I have something like:

template 
void do_something(T t){
  pass_it_somewhere(t);
  t->do_something();
}

Now it wo

相关标签:
3条回答
  • 2021-01-17 17:03

    Yet another solution: tag dispatching.

    namespace detail {
        struct tag_value {};
        struct tag_ptr {};
    
        template <bool T>  struct dispatch       { using type = tag_value; };
        template <>        struct dispatch<true> { using type = tag_ptr;   };
    
        template <class T>
        void do_call(T v, tag_value)
        {
          v.call();
        }
    
        template <class T>
        void do_call(T ptr, tag_ptr)
        {
           ptr->call();
        }
    }
    

    Then your function becomes:

    template <class T>
    void do_something(T unknown)
    {
       do_call(unknown, 
                    typename detail::dispatch<std::is_pointer<T>::value>::type{} );
    
       // found by ADL
    
    }
    

    Live Example.

    0 讨论(0)
  • 2021-01-17 17:07

    Soultion 1

    Use template specialization:

    template <class T>
    void do_something(T t){
      pass_it_somewhere(t);
      t.do_something();
    }
    
    template <class T>
    void do_something(T* t){
      pass_it_somewhere(t);    
      t->do_something();
    }
    

    Solution 2

    Add a user-defined pointer operator in class T:

    class A
    {
    public:
        void do_something() const {}        
        const A* operator->() const { return this; }
    };
    
    template <class T>
    void do_something(T t){
      pass_it_somewhere(t);      
      t->do_something();
    }
    
    0 讨论(0)
  • 2021-01-17 17:16

    You could create a dereference mechanism as below:

    template<typename T>
    std::enable_if_t<std::is_pointer<T>::value, std::remove_pointer_t<T>&> dereference(T& t) { 
      return *t; 
    }
    
    template<typename T>
    std::enable_if_t<!std::is_pointer<T>::value, T&> dereference(T& t) {
      return t;
    }
    

    and use it in your function as:

    template <class T>
    void do_something(T t){
      pass_it_somewhere(dereference(t));
      dereference(t).do_something();
    }
    

    Live Demo

    This way you'll have to do only with concrete versions of T.

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