Click here to Skip to main content
12,763,360 members (25,883 online)
Click here to Skip to main content
Add your own
alternative version


34 bookmarked
Posted 30 May 2002

Generic C++ Properties

, 9 Jun 2002 CPOL
Rate this:
Please Sign up or sign in to vote.
A system for defining properties that is not compiler specific


Recently one of the new programmers (with a Borland C++ Builder background) here at The Collective (where I work) asked if there was any way to add properties to a class. I mentioned that Visual C++ uses __declspec(property) and that it is not cross compiler compatible. But it seemed to me that there should be a way to create generic properties. So I scanned various web pages including codeproject and found some references to using a struct as a replacement. But what I wanted was a way to seamlessly switch between __declspec(property) and a generic solution. I created some structs that I liked and then I converted them to a macro based implementation: <PRE lang=c++>#define USE_DECLSPEC_PROPERTY 0 #if USE_DECLSPEC_PROPERTY #define DECLARE_PROPERTY_GET( type, getfunc, base, var ) \ __declspec( property( get=getfunc ) ) type var #define DECLARE_PROPERTY_PUT( type, putfunc, base, var ) \ __declspec( property( put=putfunc ) ) type var #define DECLARE_PROPERTY( type, getfunc, putfunc, base, var ) \ __declspec( property( get=getfunc, put=putfunc ) ) type var #else #define DECLARE_PROPERTY_GET( type, getfunc, base, var ) \ struct _dp_##getfunc \ { \ inline operator type() \ { \ return ((base *) ((char *) this - offsetof( base, var )))->getfunc(); \ } \ }; \ friend struct _dp_##getfunc; \ _dp_##getfunc var #define DECLARE_PROPERTY_PUT( type, putfunc, base, var ) \ struct _dp_##putfunc \ { \ inline type operator=(const type & value) \ { \ return ((base *) ((char *) this - offsetof( base, var )))->putfunc( value ); \ } \ }; \ friend struct _dp_##putfunc; \ _dp_##putfunc var #define DECLARE_PROPERTY( type, getfunc, putfunc, base, var ) \ struct _dp_##getfunc_##putfunc \ { \ inline operator type() \ { \ return ((base *) ((char *) this - offsetof( base, var )))->getfunc(); \ } \ inline type operator=(const type & value) \ { \ return ((base *) ((char *) this - offsetof( base, var )))->putfunc( value ); \ } \ }; \ friend struct _dp_##getfunc_##putfunc; \ _dp_##getfunc_##putfunc var #endif

At this point I figured I would create a template that any CWnd derived class could use to add a bunch of properties: <PRE lang=c++>template <class T> class CWndProperties : public T, public CWndPropertiesImpl { public: CWndProperties() : CWndPropertiesImpl( this ) { } DECLARE_PROPERTY( bool, Wnd_GetShow, Wnd_PutShow, CWndProperties<T>, wShow ); DECLARE_PROPERTY( CRect, Wnd_GetRect, Wnd_PutRect, CWndProperties<T>, wRect ); DECLARE_PROPERTY( DWORD, Wnd_GetStyle, Wnd_PutStyle, CWndProperties<T>, wStyle ); DECLARE_PROPERTY( DWORD, Wnd_GetStyleEx, Wnd_PutStyleEx, CWndProperties<T>, wStyleEx ); };

To reduce compile times and potential code bloat CWndPropertiesImpl was created:
.h file <PRE lang=c++>class CWndPropertiesImpl { public: CWndPropertiesImpl(CWnd * pWnd = NULL); void Wnd_SetWnd(CWnd * pWnd); bool Wnd_GetShow(); bool Wnd_PutShow(const bool & bShow); CRect Wnd_GetRect(); CRect Wnd_PutRect(const CRect & rc); DWORD Wnd_GetStyle(); DWORD Wnd_PutStyle(const DWORD & dwStyle); DWORD Wnd_GetStyleEx(); DWORD Wnd_PutStyleEx(const DWORD & dwStyleEx); private: CWnd * m_pWnd; };

.cpp file <PRE lang=c++>CWndPropertiesImpl::CWndPropertiesImpl(CWnd * pWnd) { m_pWnd = pWnd; } void CWndPropertiesImpl::Wnd_SetWnd(CWnd * pWnd) { m_pWnd = pWnd; } bool CWndPropertiesImpl::Wnd_GetShow() { return m_pWnd->IsWindowVisible() ? true : false; } bool CWndPropertiesImpl::Wnd_PutShow(const bool & bShow) { bool bReturn = Wnd_GetShow(); m_pWnd->ShowWindow( bShow ? SW_SHOW : SW_HIDE ); return bReturn; } CRect CWndPropertiesImpl::Wnd_GetRect() { CRect rcReturn; m_pWnd->GetWindowRect( &rcReturn ); return rcReturn; } CRect CWndPropertiesImpl::Wnd_PutRect(const CRect & rc) { CRect rcReturn = Wnd_GetRect(); m_pWnd->SetWindowPos( NULL, rc.left,, rc.Width(), rc.Height(), SWP_NOZORDER | SWP_NOACTIVATE ); return rcReturn; } DWORD CWndPropertiesImpl::Wnd_GetStyle() { return m_pWnd->GetStyle(); } DWORD CWndPropertiesImpl::Wnd_PutStyle(const DWORD & dwStyle) { DWORD dwReturn = Wnd_GetStyle(); m_pWnd->ModifyStyle( 0xFFFFFFFF, dwStyle ); return dwReturn; } DWORD CWndPropertiesImpl::Wnd_GetStyleEx() { return m_pWnd->GetExStyle(); } DWORD CWndPropertiesImpl::Wnd_PutStyleEx(const DWORD & dwStyleEx) { DWORD dwReturn = Wnd_GetStyleEx(); m_pWnd->ModifyStyleEx( 0xFFFFFFFF, dwStyleEx ); return dwReturn; }

Now all I needed to do was derive my window class from the CWndProperties template - passing in the class that I originally derived my class from and that was it: <PRE lang=c++>class CNewTreeCtrl : public CWndProperties<CTreeCtrl> ... CNewTreeCtrl wndTree; ... wndTree.wShow = false; // this hides the window wndTree.wShow = true; // this shows the window wndTree.wShow = !wndTree.wShow // this toggles the windows visibility


As a generic solution, this will work on different machines with different compilers. It can also reduce the API/framework that someone new to (let's say) MFC might need to learn. It is backwards compatible with classes already defined. And, in my opinion, once established the code will look cleaner and easier to read.


OK, so there are a few problems. First, the generic solution still uses at least 1 byte per property; and on Visual C++ it rounds up to the next 4 byte boundry. Second, the generic solution is not able to do property arrays.


The Collective is a company that makes video games that run on multiple platforms. The use of generic properties is appealing, but will likely have limited use within areas that need to be optimized. I know that I'll use them in the Tools department, but it's adoption in other departments will need to be limited to classes where every ounce of speed or memory is not an issue.

Revision history

June 1st 2002 - Initial revision.
June 4th 2002 - Removed dependency on the (4 byte) pThis variable for every property; it now only requires 1 byte per property. Thanks to Matthias Mann who made this suggestion in his comments.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author
Web Developer
United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

QuestionWhat is offset? I implemented all like this, please comment Pin
Axiom66622-May-08 6:54
memberAxiom66622-May-08 6:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170217.1 | Last Updated 10 Jun 2002
Article Copyright 2002 by
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid