polymorphism on template parameters

Discussion in 'C++' started by Renato Golin, Aug 5, 2008.

  1. Renato Golin

    Renato Golin Guest

    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 = ReproducePolicy
    >

    class 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

    --
    Reclaim your digital rights, eliminate DRM, learn more at
    http://www.defectivebydesign.org/what_is_drm
     
    Renato Golin, Aug 5, 2008
    #1
    1. Advertising

  2. Renato Golin

    Renato Golin Guest

    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 = NoReproduce
    >

    class 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


    --
    Reclaim your digital rights, eliminate DRM, learn more at
    http://www.defectivebydesign.org/what_is_drm
     
    Renato Golin, Aug 5, 2008
    #2
    1. Advertising

  3. Renato Golin

    Joe Greer Guest

    Renato Golin <> wrote in
    news:48984b94$0$639$:

    >
    > 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 = 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());
    s ->DoThing();
    delete s; // virtual destructor lets this work
    return 0;
    }

    HTH,
    joe
     
    Joe Greer, Aug 5, 2008
    #3
  4. Renato Golin

    Renato Golin Guest

    Pete Becker wrote:
    > 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


    --
    Reclaim your digital rights, eliminate DRM, learn more at
    http://www.defectivebydesign.org/what_is_drm
     
    Renato Golin, Aug 5, 2008
    #4
  5. Renato Golin

    Renato Golin Guest

    Joe Greer wrote:
    > 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


    --
    Reclaim your digital rights, eliminate DRM, learn more at
    http://www.defectivebydesign.org/what_is_drm
     
    Renato Golin, Aug 5, 2008
    #5
  6. Renato Golin

    kwikius Guest

    "Joe Greer" <> wrote in message
    news:Xns9AF161C82B08Bjgreerdoubletakecom@85.214.90.236...

    > 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
     
    kwikius, Aug 5, 2008
    #6
  7. Renato Golin

    anon Guest

    Joe Greer wrote:
    > 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());


    Shouldn't this be dynamic_cast< IThing* > instead?

    > s ->DoThing();
    > delete s; // virtual destructor lets this work
    > return 0;
    > }
     
    anon, Aug 5, 2008
    #7
  8. Renato Golin

    Joe Greer Guest

    anon <> wrote in news:g79oe1$l7v$:

    >
    > Shouldn't this be dynamic_cast< IThing* > instead?
    >
    >> s ->DoThing();
    >> delete s; // virtual destructor lets this work
    >> return 0;
    >> }

    >


    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
     
    Joe Greer, Aug 5, 2008
    #8
  9. Renato Golin

    Joe Greer Guest

    anon <> wrote in news:g79oe1$l7v$:

    >
    > Shouldn't this be dynamic_cast< IThing* > instead?
    >
    >> s ->DoThing();
    >> delete s; // virtual destructor lets this work
    >> return 0;
    >> }

    >


    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
     
    Joe Greer, Aug 5, 2008
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Krivenok Dmitry
    Replies:
    13
    Views:
    1,493
    Axter
    Jun 1, 2006
  2. vsgdp
    Replies:
    3
    Views:
    318
    Jim Langston
    May 5, 2007
  3. TimeHorse
    Replies:
    0
    Views:
    331
    TimeHorse
    Aug 9, 2007
  4. none
    Replies:
    4
    Views:
    1,291
    Michael Doubez
    Mar 8, 2010
  5. kito
    Replies:
    2
    Views:
    439
Loading...

Share This Page