The Artima Developer Community
Sponsored Link

Weblogs Forum
The Static Function Pointer Table Polymorphism Pattern

3 replies on 1 page. Most recent reply: Aug 17, 2005 5:41 AM by Christopher Diggins

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 3 replies on 1 page
Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

The Static Function Pointer Table Polymorphism Pattern (View in Weblogs)
Posted: Aug 16, 2005 10:45 AM
Reply to this message Reply
Summary
A rather unpleasant name, but a very useful pattern.
Advertisement
I have been using a technique of creating static function pointer tables in order to achieve efficient signature-based polymorphism over and over again. I think it is time I elevated it to Pattern status. Here is how the Static Function Pointer Table Polymorphism Pattern works:

Let's say I want to emulate the behaviour of a duck-typed interface FuBar which looks like the following psuedo-code:

  interface FuBar {
    int Fu();
    int Bar(int x);
  }
First I declare an appropriate function pointer table type:
  struct FuBarTable {
    int(*Fu)(void* pseudo_this);
    int(*Bar)(void* pseudo_this, int x);
  };
Then I declare a static adapter.
  template<typename T>
  struct StaticFuBarAdapter {
    static int Fu(void* pseudo_this) { return reinterpret_cast<T*>(pseudo_this)->Fu(); }
    static int Bar(void* pseudo_this, int x) { return reinterpret_cast<T*>(pseudo_this)->Bar(x); }
};
Now I create a function which returns the address to a static FuBarTable for a given type T.
  template<typename T>
  FuBarTable* GetFuBarTable() {
    typedef StaticFuBarAdapter<T> U;
    static FuBarTable table = { U::Fu, U::Bar };
    return &table;
  };
Finally I bundle a pointer to the table, and a pointer to the object in a single polymorphic reference type.
  struct FuBar {
    template<typename T>
    FuBar(T& x) {
      object = &x;
      table = GetFuBarTable<T>();
    }
    int Fu() {
      return table->Fu(object);
    }
    int Bar(int x) {
      return table->Bar(object, x);
    }
  private:
    void* object;
    FuBarTable* table;
  }
Now I can write:
  struct MyFuBar {
    int Fu() { return 1; }
    int Bar(int x) { return Fu() + x; }
  };

  struct YourFuBar {
    int Fu() { return 2; }
    int Bar(int x) { return Fu() + x; }
  };

  void DoFuAndBar(FuBar fb) {
    cout << fb.Bar(fb.Fu()) << endl;
  }

  int main() {
    MyFuBar fb1;
    DoFuAndBar(fb1);
    YourFuBar fb2;
    DoFuAndBar(fb2);
  }
Voila! Polymorphism the hard way. If you can think of a better name, I am very open to suggestions.


Michel Parisien

Posts: 25
Nickname: kriggs
Registered: Jul, 2005

Re: The Static Function Pointer Table Polymorphism Pattern Posted: Aug 17, 2005 4:49 AM
Reply to this message Reply
I don't know what I would call it, but there is something rather beautiful about this... it goes around the usual way OO is done, and yet it does not offend me. I wonder if this can be scaled to large applications and not create a headache.

Terje Slettebø

Posts: 205
Nickname: tslettebo
Registered: Jun, 2004

Re: The Static Function Pointer Table Polymorphism Pattern Posted: Aug 17, 2005 5:17 AM
Reply to this message Reply
What would be the advantage of this over inheritance-based polymorphism (MyFuBar and YourFuBar inherits from FuBar)? FuBar does some computations in its constructor, so it might well be slower than using virtual functions (essentially, it looks like an emulation of virtual functions).

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: The Static Function Pointer Table Polymorphism Pattern Posted: Aug 17, 2005 5:41 AM
Reply to this message Reply
> FuBar does some computations in its constructor, so it
> might well be slower than using virtual functions

If you rewrite the constructor as:


FuBar(T& x) : object(&x), table(GetFuBarTable<T>()) { }


You have a chance the compiler can make this very efficient. GetFuBarTable() is all static computations, so it should be easily inlined by a compiler.

> (essentially, it looks like an emulation of virtual
> functions).

Yep. That is very much what it is, except for one small difference. The class internally does no dynamic dispatching.

> What would be the advantage of this over inheritance-based
> polymorphism (MyFuBar and YourFuBar inherits from FuBar)?

It is definitely not flat-out better, but it can be useful in some circumstances.

- You can plug into classes which are for some reason not modifiable, just like the External Polymorphism pattern.
- The class does not have to store a virtual table function pointer internally
- You can avoid the tight coupling which results from inheritance
- A class does not have to declare in advance it is implementing an interface, it does so incidentally. This results in duck-typing, or signature based polymorphism.
- Intra-method calls are inlinable. When one member function calls a virtual function, it can't inline it.

I hope this helps?

Flat View: This topic has 3 replies on 1 page
Topic: A Week on a SunRay – A Travelog. Part I. Previous Topic   Next Topic Topic: Going all in...

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use