Re: C++ Templates - passing a pointer to the member to that member's base class
Thanx for the input, here is what it all boiled down to. First code
sniplet with all the template code and than a macro version taht is
more readable:
-------------- Begin template code --------------
template <class C>
class Interface
{
public:
template <class T, class D>
class Property
{
public:
typedef typename Property<T, D> P;
typedef P C::* prop_mbr_ptr;
void Set(T t)
{
C * c = (C*)(((char*)this) - ((char*) &(((C*)0)->*(((D*)this)-
offset()))));
((C &) *this).Set<D, T>(t);
};
T Get() const
{
C * c = (C*)(((char*)this) - ((char*) &(((C*)0)->*(((D*)this)-
offset()))));
return ((C &) *this).Get<D, T>();
};
operator T () const { return Get();};
};
};
class Implementation : public Interface<Implementation>
{
public:
// Accessor templates (must be declared!)
template<class P, class T> void Set(T);
template<class P, class T> T Get();
private:
// the Value of the property is kept here
int _time_pos;
public:
// time_pos, a Property of int-type
class time_pos_t : public Property<int, time_pos_t>
{
friend class Property<int, time_pos_t>;
time_pos_t Implementation::* offset() { return
&Implementation::time_pos; }
public:
void operator= (const int value) { Set(value); };
} time_pos;
};
// Specializations of the accessor templates for time_pos
template<> void Implementation::Set<Implementation::time_pos_t,
int>(int i)
{
_time_pos = i;
}
template<>int Implementation::Get<Implementation::time_pos_t, int>()
{
return _time_pos;
}
void main()
{
Implementation impl;
impl.time_pos = 42;
int i = impl.time_pos;
}
-------------- End template code --------------
And now with some macro magic:
-------------- Begin macro code --------------
#define DECL_ACCESSORS() \
template<class P, class T> void Set(T); \
template<class P, class T> T Get();
#define DECL_PROPERTY(this_class, prop_name, type) \
class prop_name##_t : public Property<type, prop_name##_t> \
{ \
friend class Property<type, prop_name##_t>; \
prop_name##_t this_class::* offset() { return
&this_class::prop_name; } \
public: \
void operator= (const type value) { Set(value); }; \
} prop_name;
#define DEF_PROPERTY_GET(this_class, prop_name, type) \
template<>type this_class::Get<this_class::prop_name##_t, type>()
#define DEF_PROPERTY_SET(this_class, prop_name, type) \
template<> void this_class::Set<this_class::prop_name##_t,
type>(type value)
template <class C>
class Interface
{
public:
template <class T, class D>
class Property
{
public:
typedef typename Property<T, D> P;
typedef P C::* prop_mbr_ptr;
void Set(T t)
{
C * c = (C*)(((char*)this) - ((char*) &(((C*)0)->*(((D*)this)-
offset()))));
((C &) *this).Set<D, T>(t);
};
T Get() const
{
C * c = (C*)(((char*)this) - ((char*) &(((C*)0)->*(((D*)this)-
offset()))));
return ((C &) *this).Get<D, T>();
};
operator T () const { return Get();};
};
};
class Implementation2 : public Interface<Implementation2>
{
public:
DECL_ACCESSORS()
private:
// the Value of the property is kept here
int _time_pos;
public:
// time_pos, a Property of int-type
DECL_PROPERTY(Implementation2, time_pos, int)
};
// Specializations of the accessor templates for time_pos
DEF_PROPERTY_SET(Implementation2, time_pos, int)
{
_time_pos = value;
}
DEF_PROPERTY_GET(Implementation2, time_pos, int)
{
return _time_pos;
}
void main()
{
Implementation2 impl2;
impl2.time_pos = 42;
int j = impl2.time_pos;
}
-------------- End macro code --------------
I added some operators to make properties look more like "variables".
Two improvments could be
1. Let the DECL_ACCESSORS() generate "typedef this_class _this_class"
and not to repeat the declaring class in the rest of the macros.
2. To add "typedef T type;" inside "template <class T, class D> class
Property" and use class this_class::property_name::type, so that one
doesn't have to repeat the type in the DEF_PROPERTY_GET/
DEF_PROPERTY_SET macros.
However, my compiler seems to get crazy when I do that. Anyway, I'm
pretty satisfied now, it's possible to declare a property in one line
of code in the class declaration and use it in the same way as in
C#...
Feel free to come with more suggestions!
BR // Jonas
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]