Boost logo

Boost :

From: Karl Nelson (kenelson_at_[hidden])
Date: 2002-02-13 20:05:29


Someone in this group must have been reading gtkmm code again.

> >
> > #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;
> > };
> >
> Borland C++ 5.5.1 says:
>
> "union member Windows::Width is of type class with operator ="
>
> I can't get to the corresponding clauses to see if it is right; but if it
> is, the technique is non conformant.

I have a lot of experience which the above anonymous union construct
(I wrote an entire C++ library using it - gtkmm). Although it
saves space it is not a good idea. An anonymous union is only supposed
to hold classes which have trivial ctor, dtor and copy constructors
according to the standard. Thus operator= is not allowed to be
defined. Because of this on many compilers doing operator = will
from one property to another will replace the pointer in the union.
Thus it breaks the properties.

In short don't use anonymous unions. Unions are not defined to
be anything useful in C++, simply there for compatiblity.
There is no reason to require classes in unions to be trivial
as the user should be expected to chose the proper ctor with
placement new, and dtor with explicit dtor and copy in the
event the union needs to be copied.

You are MUCH MUCH better off using properties by accessor...

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

struct Window
  {
     PROPERTY(Window, int, Width) width() const;
     PROPERTY(Window, int, Height) height() const;
  }

 PROPERTY(Window, int, Width) Window::width() const
   { return this; }
 PROPERTY(Window, int, Height) Window::height() const
   { return this; }

main()
{
  Window w;
  w.width()=10;
  w.height()=10;
  cout << w.width();
  cout << w.height();
}

It is smaller, safer, properties can be virtual if you make it so the
property so that it doesn't expose its implementation, you can have
private and public properties.

--Karl


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