//
// MetaPointer
//
// This MetaObject descendant can contain any type of object that is
// copyable. The object it contains is accessible via the dereference
// and deref-access (arrow) operators, as if this class were a smart
// pointer.
//
template<typename T> class MetaPointer : public MetaObject
{
protected:
   T containedObject;
 
public:
   MetaPointer(const char *className, const char *key)
      : MetaObject(className, key), containedObject()
   {
   }
  
   MetaPointer(const char *className, const char *key, const T &initValue)
      : MetaObject(className, key), containedObject(initValue)
   {
   }

   MetaPointer(const MetaPointer<T> &other) 
      : MetaObject(other), containedObject(other.containedObject)
   {
   }
  
   MetaObject *clone() const { return new MetaPointer<T>(*this); }
  
   // NB: inheriting classes should override MetaObject::toString if they
   // are interested in doing so.
  
   // Operators 
   T *operator -> () { return &containedObject; }
   T &operator *  () { return containedObject;  }
};

//==============================================================================

class MetaQStringPtr : public MetaPointer<qstring>
{
public:
   MetaQStringPtr(const char *key) : MetaPointer<qstring>("MetaQStringPtr", key)
   {
   }
   
   MetaQStringPtr(const char *key, const qstring &initValue)
      : MetaPointer<qstring>("MetaQStringPtr", key, initValue)
   {
   }

   MetaQStringPtr(const char *key, const char *value)
      : MetaPointer<qstring>("MetaQStringPtr", key)
   {
      containedObject = value;
   }
   
   MetaQStringPtr(const MetaQStringPtr &other)
     : MetaPointer<qstring>(other)
   {
   }
      
   MetaObject *clone() const { return new MetaQStringPtr(*this); }
   
   const char *toString() const { return containedObject.constPtr(); }
};

//==============================================================================

// Example

#if 0

#include <cstdio>
#include "metaqstring.h"

int main()
{
   MetaTable tbl = MetaTable("example");

   // put it in the table
   tbl.addObject(new MetaQStringPtr("string", "Hello, world?"));

   // Later, get it back out.
   // (Pretend we don't know it's in there)
   
   MetaObject *obj;
   
   if((obj = tbl.getObjectType("MetaQStringPtr")))
   {
      MetaQStringPtr &mqstr = static_cast<MetaQStringPtr &>(*obj);
      
      // Direct access to qstring members with operator ->
      
      mqstr->replace("?", '!');
      std::printf("%s\n", mqstr->constPtr());
      
      // Direct referential access to the object with operator *
      *mqstr = "Now, goodbye.";
      
      std::printf("%s\n", mqstr->constPtr());
   }   
   return 0;
}

/*

  Output:

  Hello, world!
  Now, goodbye.

*/

#endif