template specialization

E

Eric

Does anyone know if you can specialize a template function for
arguments that are pointers to a particular base class and not lose
the subclass type?

example:

template <class E>
void DeliverEvent(E *Event);

is a function that will receive an Event object, and then eventually
pass it to the proper destination. To avoid downcasting, any
destination will have a "ReceiveEvent" function that is overloaded for
each specific Event class it is interested in.

There is a particular class of Events, call them "CallEvents", which
require special processing before passing them along. So I want to
specialize the function as such:

template <>
void DeliverEvent(CircuitEvent *Event);

But in doing it this way, the Event object becomes a base class
pointer, and I lose its specific type (and I would like to avoid
downcasting to regain it).

Is there a way to specialize the template function so that my template
argument keeps it type?

Thanks,
Eric Simon
 
J

Jeff

Hey Eric, I must be missing something here, hope I don't make a total
fool of myself ...
template <class E>
void DeliverEvent(E *Event);
template <>
void DeliverEvent(CircuitEvent *Event);

Don't you need to specify the type in the specialization (hope I've
got this right...) ?
template <>
void DeliverEvent<CircuitEvent>(CircuitEvent* Event);
------------

Second, if you're dealing with a class heirarchy, why do you need to
use templates here at all? Can't you just overload the function?
(pardon the silly question)
void DeliverEvent(Event* e);
void DeliverEvent(CircuitEvent* e);

Jeff
 
T

tom_usenet

Does anyone know if you can specialize a template function for
arguments that are pointers to a particular base class and not lose
the subclass type?

example:

template <class E>
void DeliverEvent(E *Event);

is a function that will receive an Event object, and then eventually
pass it to the proper destination. To avoid downcasting, any
destination will have a "ReceiveEvent" function that is overloaded for
each specific Event class it is interested in.

There is a particular class of Events, call them "CallEvents", which
require special processing before passing them along. So I want to
specialize the function as such:

template <>
void DeliverEvent(CircuitEvent *Event);

But in doing it this way, the Event object becomes a base class
pointer, and I lose its specific type (and I would like to avoid
downcasting to regain it).

Is there a way to specialize the template function so that my template
argument keeps it type?

Yes, but it's a bit complicated (first download boost from
www.boost.org).

Basically you don't specialize the template, but instead dispatch to a
particular implementation based on properties of the passed type. In
this case, your looking for SpecialEvent and classes derived from it.

#include <iostream>
#include <boost/type_traits.hpp>
using namespace boost;

struct Event
{
};

struct SpecialEvent
{
virtual ~SpecialEvent() {}

void non_virtual()
{
std::cout << "SpecialEvent::non_virtual\n";
}
};

struct DerivedSpecialEvent: SpecialEvent
{
void non_virtual()
{
std::cout << "DerivedSpecialEvent::non_virtual\n";
}
};

template <bool>
struct DeliverEventImpl
{
template <class Event>
static void do_it(Event* event)
{
std::cout << "Non specialized\n";
}
};

template<>
struct DeliverEventImpl<true>
{
//SpecialEvent version
template <class Event>
static void do_it(Event* event)
{
event->non_virtual();
}
};


template <class E>
void DeliverEvent(E* event)
{
DeliverEventImpl<
is_base_and_derived said:
::do_it(event);
}

int main()
{
Event e;
SpecialEvent se;
DerivedSpecialEvent dse;
DeliverEvent(&e);
DeliverEvent(&se);
DeliverEvent(&dse);
}

Tom
 
E

Eric

Hey Eric, I must be missing something here, hope I don't make a total
fool of myself ...


Don't you need to specify the type in the specialization (hope I've
got this right...) ?
template <>
void DeliverEvent<CircuitEvent>(CircuitEvent* Event);

Yes, you are right. My mistake.
------------

Second, if you're dealing with a class heirarchy, why do you need to
use templates here at all? Can't you just overload the function?
(pardon the silly question)
void DeliverEvent(Event* e);
void DeliverEvent(CircuitEvent* e);

The problem is that Event and Circuit Event are base classes. There
are several concrete classes that inherit from Event. Circuit Event
also inherits from Event, and in turn, has several concrete classes
inheriting from it. I use templates because I don't want to have to
downcast to regain the subclass type. I guess it's a very weak
hierarchy - the base class has very little functionality. Most of the
interesting stuff is specific to each subclass.

Thanks,
Eric
 
J

Jeff

Second, if you're dealing with a class heirarchy, why do you need to
The problem is that Event and Circuit Event are base classes. There
are several concrete classes that inherit from Event. Circuit Event
also inherits from Event, and in turn, has several concrete classes
inheriting from it. I use templates because I don't want to have to
downcast to regain the subclass type.

I'm still puzzled as to why you need templates, though ... shouldn't
polymorphism do the trick? In Scott Meyers's "Effective C++, 2nd ed",
Item 41 says "Differentiate between inheritance and templates" -- the
section is aimed at class templates, but can be generalized to
functions as well. The summary of the item, copied from the book, is
here:

- A template should be used to generate a collection of classes when
the type of the objects /*does not*/ affect the behaviour of the
class's functions.

- Inheritance should be used for a collection of classes when the type
of the objects /*does*/ affect the behaviour of the class's functions.

Since you're talking about changing the behaviour of a particular
function depending on the type of item passed to it, polymorphism (or,
in this case, function overloading) seems to be called for...

But perhaps I'm missing something. Can you boil your problem down to
a simple representation and post it? That way I (and others) might be
able to comment more appropriately on your problem (perhaps creating a
new thread in this group, and copying the messages from this thread to
the new post).

Jeff
 

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

No members online now.

Forum statistics

Threads
474,147
Messages
2,570,833
Members
47,380
Latest member
AlinaBlevi

Latest Threads

Top