Boost logo

Boost :

From: Kevin Atkinson (kevinatk_at_[hidden])
Date: 2000-02-26 18:17:27


Attached is some code for the concept of an Emulation which I submit for
possible inclusion in boost.

Over the years I have determined that for maximum readability all
structs, types, etc.. should be mixed case with the first letter
upper. I wish the C++ standards committee felt the same way. There are
some language (Haskell) which REQUIRE that all types begin with an upper
case letter.

The emulation concept has proved EXTREMELY useful for my Aspell package
(http://aspell.sourceforge.net).

It is in namespace autil as are all util type functions in the Aspell
package. Obviously if this in included in boost the namespace should
change. Also attached is the source for the ClonePtr which the
Emulation class uses. Fell free to comment on it also however that is
not the primary focus of this email.

As always comments most welcome.

-- 
Kevin Atkinson
kevinatk_at_[hidden]
http://metalab.unc.edu/kevina/

#ifndef __autil_emulation__
#define __autil_emulation__

#include "clone_ptr.hh"

// An emulation is an efficient way to iterate through elements much
// like a forward iterator. The at_end method is a convince method
// as emulations will return a null pointer or some other sort of
// special end state when they are at the end.
// Unlike an iterator iterating through x elements on a list can be
// done in x function calls while an iterator will require 3*x.
// function calls.
// Example of emulator usage
// const char * word;
// while ( (word = elements->next()) != 0) { // one function call
// cout << word << endl;
// }
// And an iterator
// iterator i = container->begin();
// iterator end = container->end();
// while (i != end) { // comparison, one function call
// cout << *i << endl; // deref, total of two function calls
// ++i; // increment, total of three function calls.
// }
// Normally all three calls are inline so it doesn't really matter
// but when the container type is not visible there are not inline
// and probably even virtual.
// If you really love iterators you can very easily wrap an emulation
// in a forward iterator.

namespace autil {

  template <typename Val>
  class VirEmulation {
  public:
    typedef Val Value;
    virtual VirEmulation * clone() const = 0;
    virtual void assign(const VirEmulation *) = 0;
    virtual Value next() = 0;
    virtual bool at_end() const = 0;
    virtual ~VirEmulation() {}
  };

  template <typename Val>
  class Emulation {
  public:
    typedef VirEmulation<Val> VirEmul;
    typedef Val Value;

    ClonePtr<VirEmul> p_;

  public:
    Emulation() : p_(0) {}
    Emulation(VirEmul * p) : p_(p) {}
    Emulation(const VirEmul & p) : p_(p.clone()) {}
    Emulation & operator=(VirEmul * p) {
      p_ = p;
      return *this;
    }
    
    Value next() {return p_->next();}
    bool at_end() const {return p_->at_end();}
  };

  template <class Parms>
  // Parms is expected to have the following members:
  // typename Value
  // typename Iterator;
  // bool endf(Iterator)
  // Value end_state()
  // Value deref(Iterator)
  class MakeVirEmulation : public VirEmulation<typename Parms::Value> {
  public:
    typedef typename Parms::Iterator Iterator;
  private:
    Iterator i_;
    Parms parms_;
  public:

    MakeVirEmulation(const Iterator i, const Parms & p = Parms())
      : i_(i), parms_(p) {}

    VirEmulation<Value> * clone() const {
      return new MakeVirEmulation(*this);
    }

    void assign (const VirEmulation<Value> * other) {
      *this = *static_cast<const MakeVirEmulation *>(other);
    }

    Value next() {
      if (parms_.endf(i_))
        return parms_.end_state();
      Value temp = parms_.deref(i_);
      ++i_;
      return temp;
    }

    bool at_end() const {
      return parms_.endf(i_);
    }
  };

  template <class Value>
  struct MakeAlwaysEndEmulationParms {
    Value end_state() const {return Value();}
  };

  template <class Value>
  struct MakeAlwaysEndEmulationParms<Value *> {
    Value * end_state() const {return 0;}
  };
  
  template <class Value>
  class MakeAlwaysEndEmulation : public VirEmulation<Value> {
    MakeAlwaysEndEmulationParms<Value> parms_;
  public:
    MakeAlwaysEndEmulation * clone() const {
      return new MakeAlwaysEndEmulation(*this);
    }
    void assign(const VirEmulation<Value> * that) {
      *this = *static_cast<const MakeAlwaysEndEmulation *>(that);
    }
    Value next() {return parms_.end_state();}
    bool at_end() const {return true;}
  };
}

#endif


// Copyright (c) 2000
// Kevin Atkinson
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without
// fee, provided that the above copyright notice appear in all copies
// and that both that copyright notice and this permission notice
// appear in supporting documentation. Kevin Atkinson makes no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied
// warranty.

#ifndef __autil_clone_ptr__
#define __autil_clone_ptr__

// The copy constructor calls clone to create a new copy

// The assignment operator calls the copy method of the current ptr
// unless it is null. If null it will clone the other object.

namespace autil {

  template <typename Class>
  class ClonePtr {
  public:
    Class * ptr;

    ClonePtr() : ptr(0) {}
    explicit ClonePtr(Class * p) : ptr(p) {}
    
    ClonePtr(const ClonePtr & other);
    ClonePtr & operator= (Class * p);
    ClonePtr & operator= (const ClonePtr & other) {
      assign(other.ptr);
      return *this;
    }
    
    void assign(const Class * p);

    operator Class * () const {return ptr;}
    Class & operator * ()const {return *ptr;}
    Class * operator-> () const {return ptr;}
    operator bool () const {return ptr;}

    void del();
    
    ~ClonePtr();
  };

}

#endif


// Copyright (c) 2000
// Kevin Atkinson
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without
// fee, provided that the above copyright notice appear in all copies
// and that both that copyright notice and this permission notice
// appear in supporting documentation. Kevin Atkinson makes no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied
// warranty.

#ifndef __autil_clone_ptr_t__
#define __autil_clone_ptr_t__

#include <typeinfo>
#include "clone_ptr.hh"

namespace autil {

  template <typename Class>
  ClonePtr<Class>::ClonePtr(const ClonePtr<Class> &other) {
    if (other.ptr) ptr = other.ptr->clone();
    else ptr = 0;
  }

  template <typename Class>
  inline void clone_ptr_assign_same_id(ClonePtr<Class> & ths,
                                       const Class * other_ptr)
  {
    ths.ptr->assign(other_ptr);
  }

  template <typename Class>
  inline void clone_ptr_assign_same_id(ClonePtr<const Class> & ths,
                                       const Class * other_ptr)
  {
    delete ths.ptr;
    ths.ptr = other_ptr->clone();
  }

  template <typename Class>
  void ClonePtr<Class>::assign(const Class * other_ptr)
  {
    if (ptr) {
      if (other_ptr) {
        if (typeid(*ptr) == typeid(*other_ptr)) {
          clone_ptr_assign_same_id(*this, other_ptr);
        } else {
          delete ptr;
          ptr = other_ptr->clone();
        }
      } else {
        delete ptr;
        ptr = 0;
      }
    } else {
      if (other_ptr) ptr = other_ptr->clone();
      else ptr = 0;
    }
  }
  
  template <typename Class>
  ClonePtr<Class> &
  ClonePtr<Class>::operator= (Class * other) {
    delete ptr;
    ptr = other;
    return *this;
  }

  template <typename Class>
  void ClonePtr<Class>::del() {
    delete ptr;
    ptr = 0;
  }
  
  template <typename Class>
  ClonePtr<Class>::~ClonePtr() {
    delete ptr;
  }
  
}

#endif


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk