Boost logo

Boost :

From: Brad King (brad.king_at_[hidden])
Date: 2002-02-13 17:50:14


> boost::property<A, &A::value, read<&A::get_x>, write<&A::set_x> > value;
I don't think this can work because the type of &A::value will recursively
go on forever, and you can't take the address of a declaration that has
yet to be made.

This implementation actually compiles and runs:

#define PROPERTY(c, t, n) \
  PropertyMaker< c, t >::Property<&c::Get##n, &c::Set##n> n

template <typename Class, typename Data>
struct PropertyMaker
{
  template <Data (Class::*Get)() const, void (Class::*Set)(Data)>
  struct Property
  {
    Class* m_Class;
    operator Data () const { return (m_Class->*Get)(); }
    void operator=(Data data) const { (m_Class->*Set)(data); }
  };
};

struct Window
{
  int GetWidth() const { return m_Width; }
  void SetWidth(int width) { m_Width = width; }
  int GetHeight() const { return m_Height; }
  void SetHeight(int height) { m_Height = height; }
  
  union
  {
    Window* m_Self;
    PROPERTY(Window, int, Width);
    PROPERTY(Window, int, Height);
  };
  
  Window(): m_Self(this), m_Width(1), m_Height(1) {}
  
  int m_Width;
  int m_Height;
};

This one also runs, but is a bit less safe:

#define PROPERTY(c, t, n) \
  PropertyMaker< c, t >::Property<&c::Get##n, &c::Set##n> n

template <typename Class, typename Data>
struct PropertyMaker
{
  template <Data (Class::*Get)() const, void (Class::*Set)(Data)>
  struct Property
  {
    operator Data ()
      {
        Class* c = reinterpret_cast<Class*>(this);
        return (c->*Get)();
      }
    void operator=(Data data)
      {
        Class* c = reinterpret_cast<Class*>(this);
        (c->*Set)(data);
      }
  };
};

struct Window
{
  int GetWidth() const { return m_Width; }
  void SetWidth(int width) { m_Width = width; }
  int GetHeight() const { return m_Height; }
  void SetHeight(int height) { m_Height = height; }
  
  // Must be at beginning of data.
  union
  {
    PROPERTY(Window, int, Width);
    PROPERTY(Window, int, Height);
  };
  
  Window(): m_Width(1), m_Height(1) {}
  
  int m_Width;
  int m_Height;
};

Obviously, the macro interface can be replaced with something better.

-Brad


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