Template function for pointer and non-pointer types
Hello,
I am trying to find some method to write a template function that can accept both pointer and non-pointer types and still be able to dereference them correctly. The only difference is the '.' and the '->', as shown below. Anyone have any idea how to approach this problem?
template< class T >
void foo( T t ) { t.bar(); }
template< class T >
void foo( T t ) { t->bar(); }
Thanks in advance.
[481 byte] By [
Apoapsis] at [2007-11-11 9:56:32]

# 1 Re: Template function for pointer and non-pointer types
Hi,
just write two templates with the same name, one taking a literal and the other taking a pointer. You could then call the one from the other sparing you having to replicate code:
template< class T >
void foo( T t ) { t.bar(); }
template< class T >
void foo( T* t ) { if(t !=NULL) foo(*t); }
Is that what you need?
Cheers,
D
# 2 Re: Template function for pointer and non-pointer types
As Dieter said, overload the template function with two versions: func(T t) and func(T* t).
Danny at 2007-11-11 21:00:45 >

# 3 Re: Template function for pointer and non-pointer types
Just to not let the regulars hijack this thread, I'm gonna twist my brain to find a rediculous way to do this diffrent (read dumber)...
#define THING(X) (sizeof(X)==4)?*(X):(X)
template< class T >
void foo( T t ) { THING(t).bar(); }
I know it wont work but it's fun to think about at least, especially if T is not 4 bytes :)
# 4 Re: Template function for pointer and non-pointer types
Thanks for the help everyone, and drkybelk's suggestion did work. However, I've run into another problem that I wonder if there is a solution to. I'm trying to write a templated class that can handle both objects and pointers to objects. It is a type of container, but it needs some information from the objects it is storing before it can store them, and it also needs to periodically make some ajustments based on information stored in the objects. So it needs to store the objects as either objects or pointers to objects, but it also needs to be able to dereference the objects correctly when it needs information from the objects.
Here's a simplification of the class with all the important details:
template< class T >
class SomeContainer
{
public:
void Insert( T t );
protected:
void Adjust();
std::set<T> storage;
};
template< class T >
void SomeContainer< T >::Insert( T t )
{
if( t.GetInfo() == something ) // <=== This will need to be different based on whether t is a pointer or non-pointer type
{
storage.insert( t );
}
}
template< class T >
void SomeContainer< T >Adjust::()
{
for( cur = storage.begin();
cur != storage.end();
cur++ )
{
if( cur->GetSomething() == something ) // <=== This will need to be different based on whether cur is a itererator of a pointer or non-pointer type
{
make some adjustment
}
}
}
The only way I can think of to do this is to make two differently named Insert functions one for non-pointers and one for pointers (and for the other functions that call the object member functions). This of course is not a very elegant solution. Anyone see a way to do this?
The compiler should know in time wether or not something is a pointer or not. Is there a way to make the '.' or '->' general, such that it could be either and let the pre-compiler figure it out? (something like ungamed was going for)
# 5 Re: Template function for pointer and non-pointer types
Hi ungamed,
apart from being *UGLY* this solution is also incorrect and non-portable.
UGLY, because you waive your typesafety for a quick fix by using pre-processor instructions (#define)
incorrect, because there are other types with a size of 4 (e.g. double, in many systems)
unportable, because there is no guarantee, that your pointer type has a size of 4.
on 64-bit machines it might have size 8 and who knows what comes?
C++ gives you templates for the reason to avoid pre-processor hacks. So don't let
#defines come in your way. Avoid them whereever possible (which is nearly always).
Cheers,
D
# 6 Re: Template function for pointer and non-pointer types
Back to Apoapsis' question:
Overloading is a nice solution. You don;t have to repeat entire pieces of code in each overload, simply define the pointer version like this:
void func(T t) {t.someop();}
void func(T * f)
{
func(*f);
}
However, I think that you have to explain why you need a container that stores both pointers and scalar objects. You can use the reference_wrapper class to wrap objects as references, and thus enure that the container stores polymorphic objects safely: http://www.dev-archive.com/cplus/10MinuteSolution/32792
Is that the reason why you need pointers in conrtainers?
Danny at 2007-11-11 21:04:48 >
