virtual functions and templates

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • SainTiss

    virtual functions and templates

    Hi,

    Is there an extra overhead in using virtual functions and templates?
    Or is is just the same overhead as with regular classes?

    Either way, if you'd want to avoid it, will you always end up
    with code duplication?

    For example: let's say you've got two template specializations , which
    differ only slightly... So you put the common behaviour in a
    base class...
    This is fine, but if a "common" method needs to call a "specialize d" one,
    it seems to me you're always going to need polymorphism...

    The only way around seems to be not creating the base class, and
    just copying the whole class to specialize it...

    Is there a third possibility without the disadvantages of these two?

    Thanks,

    Hans
  • tom_usenet

    #2
    Re: virtual functions and templates

    On Wed, 05 Nov 2003 11:50:26 GMT, SainTiss <stiss@gmx.ne t> wrote:
    [color=blue]
    >Hi,
    >
    >Is there an extra overhead in using virtual functions and templates?[/color]

    Sort of - each instantiation will get its own vtable and RTTI, etc.,
    and this can lead to quite a lot of code bloat when there are a large
    number of different instantiations of the template.
    [color=blue]
    >Or is is just the same overhead as with regular classes?[/color]

    Well, it is the same overhead as if you wrote all of the equivalent
    non-template code. e.g.

    class foo_int
    { //...
    };

    class foo_double
    { //...
    };

    etc.
    [color=blue]
    >
    >Either way, if you'd want to avoid it, will you always end up
    >with code duplication?[/color]

    No, there are techniques to avoid code duplication, the "curiously
    recurring template pattern" being one. Some form of parametrised
    inheritence is the key, anyway.
    [color=blue]
    >
    >For example: let's say you've got two template specializations , which
    >differ only slightly... So you put the common behaviour in a
    >base class...
    >This is fine, but if a "common" method needs to call a "specialize d" one,
    >it seems to me you're always going to need polymorphism...[/color]

    Yes, but you can use compile-time polymorphism. e.g.

    template <class Derived>
    class CommonStuff
    {
    // non-virtual functions, casting this
    // to a Derived* if necessary
    };

    template <class T>
    class MyDerived: public CommonStuff<MyD erived<T> >
    {
    //add/change whatever you like
    };

    template<>
    class MyDerived<int>: public CommonStuff<MyD erived<int> >
    {
    //add whatever you like
    };

    //and even
    class Special: public CommonStuff<Spe cial>
    {
    //...
    };

    Another alternative:

    template <class T>
    class CommonStuff
    {
    // non-virtual functions, casting this
    // to a Derived* if necessary
    };

    template <class T>
    class MyDerived: public CommonStuff<T>
    {
    //add/change whatever you like
    };

    //CommonStuff<int > not specialised
    template<>
    class MyDerived<int>: public CommonStuff<int >
    {
    //add whatever you like
    };
    [color=blue]
    >
    >The only way around seems to be not creating the base class, and
    >just copying the whole class to specialize it...[/color]

    Avoid this if possible - it's a maintainance nightmare.
    [color=blue]
    >Is there a third possibility without the disadvantages of these two?[/color]

    One of the above might be suitable.

    Tom

    Comment

    • SainTiss

      #3
      Re: virtual functions and templates

      tom_usenet wrote:
      [color=blue]
      > Another alternative:
      >
      > template <class T>
      > class CommonStuff
      > {
      > // non-virtual functions, casting this
      > // to a Derived* if necessary
      > };
      >
      > template <class T>
      > class MyDerived: public CommonStuff<T>
      > {
      > //add/change whatever you like
      > };
      >
      > //CommonStuff<int > not specialised
      > template<>
      > class MyDerived<int>: public CommonStuff<int >
      > {
      > //add whatever you like
      > };
      >[/color]

      I think I get the first alternative, but this one puzzles me a bit... How
      can the CommonStuff class cast to a Derived* if it doesn't know Derived? It
      only knows T from what I can see...

      So how exactly is this supposed to work then?

      Thanks,

      Hans

      Comment

      • tom_usenet

        #4
        Re: virtual functions and templates

        On Wed, 05 Nov 2003 22:41:03 GMT, SainTiss <stiss@gmx.ne t> wrote:
        [color=blue]
        >tom_usenet wrote:[color=green]
        >> template <class T>
        >> class CommonStuff
        >> {
        >> // non-virtual functions, casting this
        >> // to a Derived* if necessary
        >> };[/color][/color]
        [color=blue]
        >I think I get the first alternative, but this one puzzles me a bit... How
        >can the CommonStuff class cast to a Derived* if it doesn't know Derived? It
        >only knows T from what I can see...
        >
        >So how exactly is this supposed to work then?[/color]

        Copy and paste error - ignore that comment!

        Tom

        Comment

        • SainTiss

          #5
          Re: virtual functions and templates

          tom_usenet wrote:
          [color=blue]
          > On Wed, 05 Nov 2003 22:41:03 GMT, SainTiss <stiss@gmx.ne t> wrote:
          >[color=green]
          >>tom_usenet wrote:[color=darkred]
          >>> template <class T>
          >>> class CommonStuff
          >>> {
          >>> // non-virtual functions, casting this
          >>> // to a Derived* if necessary
          >>> };[/color][/color]
          >[color=green]
          >>I think I get the first alternative, but this one puzzles me a bit... How
          >>can the CommonStuff class cast to a Derived* if it doesn't know Derived?
          >>It only knows T from what I can see...
          >>
          >>So how exactly is this supposed to work then?[/color]
          >
          > Copy and paste error - ignore that comment!
          >
          > Tom[/color]

          Ok, but ignoring that comment, I don't really see how this is alternative is
          going to avoid polymorphism? How can the CommonStuff class call a
          specialized method if it doesn't know about the Derived class and can't use
          polymorphism?

          Thanks,

          Hans

          Comment

          • tom_usenet

            #6
            Re: virtual functions and templates

            On Thu, 06 Nov 2003 16:47:16 GMT, SainTiss <stiss@gmx.ne t> wrote:
            [color=blue]
            >tom_usenet wrote:
            >[color=green]
            >> On Wed, 05 Nov 2003 22:41:03 GMT, SainTiss <stiss@gmx.ne t> wrote:
            >>[color=darkred]
            >>>tom_usenet wrote:
            >>>> template <class T>
            >>>> class CommonStuff
            >>>> {
            >>>> // non-virtual functions, casting this
            >>>> // to a Derived* if necessary
            >>>> };[/color]
            >>[color=darkred]
            >>>I think I get the first alternative, but this one puzzles me a bit... How
            >>>can the CommonStuff class cast to a Derived* if it doesn't know Derived?
            >>>It only knows T from what I can see...
            >>>
            >>>So how exactly is this supposed to work then?[/color]
            >>
            >> Copy and paste error - ignore that comment!
            >>
            >> Tom[/color]
            >
            >Ok, but ignoring that comment, I don't really see how this is alternative is
            >going to avoid polymorphism? How can the CommonStuff class call a
            >specialized method if it doesn't know about the Derived class and can't use
            >polymorphism ?[/color]

            It does know about the derived class if there is only one derived
            class:

            template <class T>
            struct Derived;

            template <class T>
            struct Base
            {
            int f()
            {
            return static_cast<Der ived<T>*>(this)->g() + 1;
            }
            };

            template <class T>
            struct Derived: public Base<T>
            {
            int g()
            {
            return 10;
            }
            };

            template <>
            struct Derived<int> : public Base<int>
            {
            int g()
            {
            return 3000;
            }
            };

            #include <iostream>

            int main()
            {
            Derived<double> d;
            std::cout << d.f() << '\n';
            Derived<int> i;
            std::cout << i.f() << '\n';
            }

            The more general solution (for multiple derived classes) is the other
            one I presented.

            Tom

            Comment

            Working...