The Artima Developer Community
Sponsored Link

Heron-Centric: Ruminations of a Language Designer
The Static Function Pointer Table Polymorphism Pattern
by Christopher Diggins
August 16, 2005
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.

Talk Back!

Have an opinion? Readers have already posted 3 comments about this weblog entry. Why not add yours?

RSS Feed

If you'd like to be notified whenever Christopher Diggins adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

Christopher Diggins is a software developer and freelance writer. Christopher loves programming, but is eternally frustrated by the shortcomings of modern programming languages. As would any reasonable person in his shoes, he decided to quit his day job to write his own ( www.heron-language.com ). Christopher is the co-author of the C++ Cookbook from O'Reilly. Christopher can be reached through his home page at www.cdiggins.com.

This weblog entry is Copyright © 2005 Christopher Diggins. All rights reserved.

Sponsored Links



Google
  Web Artima.com   

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