template class problem

J

jiake2007

Hi all,

I'm trying to write a template class that calls a function from one of
its template parameters:

template <class T>
class Foo
{
public:
Foo(T t): t(t) {}

void doFoo() {
t.doTheStuff();
}

private:
T t;
};


The problem is: t.doTheStuff() obviously works only if T is non-
pointer, and otherwise it has to be t->doTheStuff().

My question is: is there a way to implement a template class that
would work with all types regardless of if T is a pointer or not?

Thanks all,

-J
 
M

mlimber

I'm trying to write a template class that calls a function from one of
its template parameters:

template <class T>
class Foo
{
public:
Foo(T t): t(t) {}

void doFoo() {
t.doTheStuff();
}

private:
T t;

};

The problem is: t.doTheStuff() obviously works only if T is non-
pointer, and otherwise it has to be t->doTheStuff().

My question is: is there a way to implement a template class that
would work with all types regardless of if T is a pointer or not?

There are a number of ways to handle it. You could only pass objects,
not pointer; you could specialize your class for T*; you could write
an invoker class that is specialized for T and T*; you could convert
your T member to use a smart pointer like std::tr1::shared_ptr (aka
boost::shared_ptr) that accepts a custom deleter and set it to do
nothing for incoming pointers but let it do things normally for copied
values; etc. etc.

Cheers! --M
 
A

amparikh

Hi all,

I'm trying to write a template class that calls a function from one of
its template parameters:

template <class T>
class Foo
{
public:
Foo(T t): t(t) {}

void doFoo() {
t.doTheStuff();
}

private:
T t;

};

The problem is: t.doTheStuff() obviously works only if T is non-
pointer, and otherwise it has to be t->doTheStuff().

My question is: is there a way to implement a template class that
would work with all types regardless of if T is a pointer or not?

Thanks all,

-J

Look up type traits and template specialization.
 
J

John Harrison

Hi all,

I'm trying to write a template class that calls a function from one of
its template parameters:

template <class T>
class Foo
{
public:
Foo(T t): t(t) {}

void doFoo() {
t.doTheStuff();
}

private:
T t;
};


The problem is: t.doTheStuff() obviously works only if T is non-
pointer, and otherwise it has to be t->doTheStuff().

My question is: is there a way to implement a template class that
would work with all types regardless of if T is a pointer or not?

Thanks all,

-J

struct True {};
struct False {};

template <class T>
struct IsAPointer
{
typedef False result;
};

template <class T>
struct IsAPointer<T*>
{
typedef True result;
};

template <class T>
class Foo
{
public:
Foo(T t): t(t) {}

void doFoo() {
doFooHelper(typename IsAPointer<T>::result());
}

private:
T t;

void doFooHelper(True ptr)
{
t->doTheStuff();
}

void doFooHelper(False ptr)
{
t.doTheStuff();
}
};

Untested but something like that should work.

Of course there are libraryies that already have stuff like IsAPointer
written for you. You might want to look at type_traits at www.boost.org.

john
 
P

pedro

Hi again...

I tried the following:
(T and Key are template variables from the surrounding class)


struct False {};
struct True {};
template<class U> struct IsAPointer { typedef False result; };
template<class U> struct IsAPointer<U*> { typedef True result; };

bool equals(T entry, Key key, False) { return entry.equals(key); }
bool equals(T entry, Key key, True) { return entry->equals(key); }


In principle this works, but when I do:

if (equals(*tmp->data, key, typename IsAPointer<T>::result()))

later in the code, destructor for the pointed data gets called, which
obviously is not the intention. What's wrong with the picture? How to
get around this....

Thanks again!

-J
 
J

John Harrison

pedro said:
Hi again...

I tried the following:
(T and Key are template variables from the surrounding class)


struct False {};
struct True {};
template<class U> struct IsAPointer { typedef False result; };
template<class U> struct IsAPointer<U*> { typedef True result; };

bool equals(T entry, Key key, False) { return entry.equals(key); }
bool equals(T entry, Key key, True) { return entry->equals(key); }


In principle this works, but when I do:

if (equals(*tmp->data, key, typename IsAPointer<T>::result()))

later in the code, destructor for the pointed data gets called, which
obviously is not the intention. What's wrong with the picture? How to
get around this....

Thanks again!

-J

The pointed to data is of type T, is that right? And the destructor is
called in the case when T is not a pointer? If that's the case then the
destructor is being called because you are passing by value to the
function equals (in other words its the parameter 'entry' that is being
destructed). Change to a reference (preferably a const one).

bool equals(const T& entry, Key key, False) { return entry.equals(key); }

If I got that wrong you'll need to show me a bit more code.

john
 
P

pedro

Yep, that was it. I thought it has to be something like that, but
seems I'm too tired to see by myself ;-)

Anyway, problem solved. Thanks a lot!

-J
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,225
Latest member
Top Crypto Podcasts

Latest Threads

Top