Have a template parameter, which can be a pointer type or not a pointer

Suppose I have something like:

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

It would now be useful for T allow the type of pointer or non-pointer. The do_something(...) function can basically handle pointers and not pointers except t->do_something() . For pointers I will need -> and for non pointers, I will need . to access items.

Is there any way to make T accept pointers and pointers without pointers?

+6
c ++ pointers c ++ 11 templates
source share
3 answers

You can create a dereference mechanism as shown 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 like:

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

Live demo

Thus, you only have to make specific versions of T

+9
source share

Soultion 1

Use specialized 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(); } 

Decision 2

Add a custom 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(); } 
+7
source share

Another solution: send tags.

 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 will look like this:

 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 .

+2
source share

All Articles