Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Suppose I have something like:

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

Now it would be useful that T is allowed to be a pointer- or a non-pointer type. Function do_something(...) can basically handle pointers and non-pointers, except for the t->do_something(). For pointers, I would need a -> and for non-pointers, I would need a . to access members.

Is there a way to make T accept pointers and non-pointers?

like image 670
Michael Avatar asked Apr 28 '16 14:04

Michael


People also ask

Which parameter is allowed for non-type template?

Which parameter is legal for non-type template? Explanation: The following are legal for non-type template parameters:integral or enumeration type, Pointer to object or pointer to function, Reference to object or reference to function, Pointer to member.

Can template type be a pointer?

A template has only one type, but a specialization is needed for pointer, reference, pointer to member, or function pointer types. The specialization itself is still a template on the type pointed to or referenced.

What is template type parameter?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

What is non-type parameter in template C++?

A non-type template argument provided within a template argument list is an expression whose value can be determined at compile time. Such arguments must be constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.


2 Answers

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.

like image 91
101010 Avatar answered Oct 21 '22 22:10

101010


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();
}
like image 35
Mohamad Elghawi Avatar answered Oct 21 '22 22:10

Mohamad Elghawi