The Artima Developer Community
Sponsored Link

Heron-Centric: Ruminations of a Language Designer
boost::any meet ootl::any_ptr
by Christopher Diggins
May 13, 2005
Summary
The boost::any type is a very important type in that it can hold any object which has a copy-constructor. However if you don't want to hold a copy of the value you can instead refer to the object using the ootl::any_ptr type.

Advertisement

My ootl::any_ptr class can point to any object with a copy-constructor, and provides the following public functions:

  void Delete();
  any_ptr Clone() const;
  const type_info& GetType();
  template<typename ValueType> ValueType* PtrCast();
The implementation is below:
  // this class can point to any copy-constructible value_type
  // and let you clone or delete it safely
  class any_ptr
  {
  public:
    // forward declarations
    template <class T>
    struct functions;


    template <class T>
    any_ptr(T* x)
      : m_a(x), m_t(&functions<T>::table)
    {}

    any_ptr()
      : m_a(NULL), m_t(NULL)
    {}

    void Delete() {
      assert(m_a != NULL);
      m_t->Delete(m_a);
      m_a = NULL;
    }
    any_ptr Clone() const {
      any_ptr o(*this);
      o.m_a = m_t->Clone(m_a);
      return o;
    }
    const std::type_info& GetType() const {
      return m_t->GetType(m_a);
    }
    template<typename ValueType>
    ValueType* PtrCast() {
      if (!(typeid(ValueType) == GetType())) {
        throw BadObjectCast();
      }
      return static_cast<ValueType*>(m_a);
    }

    // Function table type
    // order is important, must match all other lists of functions
    struct table {
      void (*Delete)(void*);
      const std::type_info& (*GetType)(void*);
      void* (*Clone)(void*);
    };

    // For a given referenced type T, generates functions for the
    // function table and a static instance of the table.
    template<class T>
    struct functions
    {
      static typename any_ptr::table table;
      static void Delete(void* p) {
        delete static_cast<T*>(p);
      }
      static const std::type_info& GetType(void* p) {
        return typeid(T);
      }
      static void* Clone(void* p) {
        return new T(*static_cast<T*>(p));
      }
    };
  private:
    void* m_a;
    table* m_t;
  };

  template<class T>
  typename any_ptr::table
  any_ptr::functions<T>::table = {
    &any_ptr::template functions<T>::Delete
    ,&any_ptr::template functions<T>::GetType
    ,&any_ptr::template functions<T>::Clone
  };
Those paying close attention to my work, and not intimidated by complex template code, may realize that lately I have been riding in to town with the same horse, but painting it different colors.

What I mean to say is that the basic idea is always the same, create a function pointer table at compile time for every assignment or copy-construction to a different type. Each generated function in the table is responsible for casting the internal pointer to the appropriate type.

Hopefully all this makes some sense, and industrious readers can contribute some interesting applications of this class and/or technique.

Talk Back!

Have an opinion? Readers have already posted 1 comment 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