polymorphism on template parameters

R

Renato Golin

Hi all,

I'm fiddling with policies but I'm having some problems...

My Code:

class MovePolicy { };
class EatPolicy { };
class ReproducePolicy { };

template <
class Move = MovePolicy,
class Eat = EatPolicy,
class Reproduce = ReproducePolicyclass Thing : public Move, Eat, Reproduce
{
public:
Thing() { }
virtual ~Thing() { }
};

class NoMove : public MovePolicy { };
class NoEat : public EatPolicy { };
class NoReproduce : public ReproducePolicy { };

class Stone : public Thing <NoMove, NoEat, NoReproduce>
{
public:
Stone() { }
~Stone() { }
};

int
main () {
Thing<>* s = new Stone();
return 0;
}

I get the error:

In function ‘int main()’:
error: cannot convert ‘Stone*’ to ‘Thing<MovePolicy, EatPolicy,
ReproducePolicy>*’ in initialization


Any pointers (that doesn't start with 0x...) on the subject are appreciated.

cheers,
--renato
 
R

Renato Golin

Addendum: This works, of course... but won't give me the freedom I need
to do what I want.


class MovePolicy { };
class EatPolicy { };
class ReproducePolicy { };

class NoMove : public MovePolicy { };
class NoEat : public EatPolicy { };
class NoReproduce : public ReproducePolicy { };

template <
class Move = NoMove,
class Eat = NoEat,
class Reproduce = NoReproduceclass Thing : public Move, Eat, Reproduce
{
public:
Thing() { }
virtual ~Thing() { }
};

class Stone : public Thing <NoMove, NoEat, NoReproduce>
{
public:
Stone() { }
~Stone() { }
};

int
main () {
Thing<>* s = new Stone();
return 0;
}


cheers,
--renato
 
J

Joe Greer

Hi all,

I'm fiddling with policies but I'm having some problems...

I get the error:

In function ‘int main()’:
error: cannot convert ‘Stone*’ to ‘Thing<MovePolicy, EatPolicy,
ReproducePolicy>*’ in initialization


Any pointers (that doesn't start with 0x...) on the subject are
appreciated.

cheers,
--renato

Sadly, that is both the curse and blessing of policy based design.
Different template parameters create completely new types. The template
name itself doesn't imply interaction capability between the instances.
That is one of the reasons that shared_ptr<> in TR1 isn't a policy based
smart pointer.

I have two suggestions as to how to organize things to get around this
feature of templates.

First, Instead of policies, you can use strategies that get
configured/set by the constructor. In other words, don't use templates
in this way if you want the resulting types to interact as if they were
the same type.

Or, you can define an interface for the basic 'Thing'-ness and make all
your templated classes inherit from that and only use the template for
construction. i.e.

class IThing
{
public:
virtual void DoThing() = 0;
virtual ~IThing() {}
};

class MovePolicy { };
class EatPolicy { };
class ReproducePolicy { };

template <
class Move = MovePolicy,
class Eat = EatPolicy,
class Reproduce = ReproducePolicyclass Thing : public IThing, Move, Eat, Reproduce
{
public:
Thing() { }
virtual ~Thing() { }
virtual DoThing() {}
};

class NoMove : public MovePolicy { };
class NoEat : public EatPolicy { };
class NoReproduce : public ReproducePolicy { };

class Stone : public Thing <NoMove, NoEat, NoReproduce>
{
public:
Stone() { }
~Stone() { }
};

int
main () {
IThing * s = static_cast<IThing *>(new Stone());
s ->DoThing();
delete s; // virtual destructor lets this work
return 0;
}

HTH,
joe
 
R

Renato Golin

Pete said:
First, when things start getting tangled, reduce the number of template
arguments. That makes it easier to see what's going on. After you've
figured things out, add the rest of the details back in.

Hi Pete,

The example was too simple to get tangled by that... ;)

Thing<MovePolicy etc.> and Thing<NoMove etc.> are two unrelated types.
The same problem occurs in this code:

class Base1 { };
class Base2 { };
class Derived : public Base1 { };
Base2 *ptr = new Derived; // error: no conversion from Derived* to
Base2*

You don't need to go that far, int* foo = new float; won't work either.

Templates are defined compile-time and types are created, this is why it
wouldn't work anyway. What I wanted was another way to have the same
"effect" as I would have if that did work... ;)

thanks,
--renato
 
R

Renato Golin

Joe said:
First, Instead of policies, you can use strategies that get
configured/set by the constructor. In other words, don't use templates
in this way if you want the resulting types to interact as if they were
the same type.

Hi Joe,

That's what I wanted to hear, actually. I couldn't see a way of doing it
with templates and policies, but I could be wrong... :(

The whole point of my exercise was to explore the potential of policies
so I don't need to go any further. Using strategies would work for sure,
but that wouldn't be innovative... ;)

Or, you can define an interface for the basic 'Thing'-ness and make all
your templated classes inherit from that and only use the template for
construction. i.e.

class IThing
{
public:
virtual void DoThing() = 0;
virtual ~IThing() {}
};

Hum... That might work as I want it... yes.

There is only one problem, the base class would end up defining all
methods of all sub-classes. When one adds a new sub-class you need to
change the base class.

cheers,
--renato
 
K

kwikius

First, Instead of policies, you can use strategies that get
configured/set by the constructor. In other words, don't use templates
in this way if you want the resulting types to interact as if they were
the same type.

Yep. Designs that use policies are always rubbish.

regards
Andy Little
 
A

anon

Joe said:
class IThing
{
public:
virtual void DoThing() = 0;
virtual ~IThing() {}
};

class MovePolicy { };
class EatPolicy { };
class ReproducePolicy { };

template <
class Move = MovePolicy,
class Eat = EatPolicy,
class Reproduce = ReproducePolicy
class Thing : public IThing, Move, Eat, Reproduce
{
public:
Thing() { }
virtual ~Thing() { }
virtual DoThing() {}
};

class NoMove : public MovePolicy { };
class NoEat : public EatPolicy { };
class NoReproduce : public ReproducePolicy { };

class Stone : public Thing <NoMove, NoEat, NoReproduce>
{
public:
Stone() { }
~Stone() { }
};

int
main () {
IThing * s = static_cast<IThing *>(new Stone());
 
J

Joe Greer

Can be, but doesn't have to be. static_cast<> works great if you are
dealing with the actual type of the object. You would need dynamic_cast<>
if we had a IThing * and wanted to get back to a Stone object though.

joe
 
J

Joe Greer

Can be, but doesn't have to be. static_cast<> works great if you are
dealing with the actual type of the object. You would need dynamic_cast<>
if we had a IThing * and wanted to get back to a Stone object though.

joe
 

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
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top