He estado desarrollando una biblioteca GUI para Windows (como un proyecto lateral personal, sin aspiraciones de utilidad). Para mi clase de ventana principal, he configurado una jerarquía de clases de opciones (usando el Named Parameter Idiom), porque algunas opciones se comparten y otras son específicas para determinados tipos de ventanas (como los cuadros de diálogo).¿Mejor manera de usar el lenguaje personalizado de parámetros de C++?
La manera en que funciona el parámetro Named Parameter, las funciones de la clase de parámetro tienen que devolver el objeto al que están llamados. El problema es que, en la jerarquía, cada uno tiene que ser una clase diferente - la clase createWindowOpts
para ventanas estándar, la clase createDialogOpts
para diálogos y similares. He tratado con eso haciendo todas las plantillas de clases de opciones. He aquí un ejemplo:
template <class T>
class _sharedWindowOpts: public detail::_baseCreateWindowOpts {
public: ///////////////////////////////////////////////////////////////
// No required parameters in this case.
_sharedWindowOpts() { };
typedef T optType;
// Commonly used options
optType& at(int x, int y) { mX=x; mY=y; return static_cast<optType&>(*this); }; // Where to put the upper-left corner of the window; if not specified, the system sets it to a default position
optType& at(int x, int y, int width, int height) { mX=x; mY=y; mWidth=width; mHeight=height; return static_cast<optType&>(*this); }; // Sets the position and size of the window in a single call
optType& background(HBRUSH b) { mBackground=b; return static_cast<optType&>(*this); }; // Sets the default background to this brush
optType& background(INT_PTR b) { mBackground=HBRUSH(b+1); return static_cast<optType&>(*this); }; // Sets the default background to one of the COLOR_* colors; defaults to COLOR_WINDOW
optType& cursor(HCURSOR c) { mCursor=c; return static_cast<optType&>(*this); }; // Sets the default mouse cursor for this window; defaults to the standard arrow
optType& hidden() { mStyle&=~WS_VISIBLE; return static_cast<optType&>(*this); }; // Windows are visible by default
optType& icon(HICON iconLarge, HICON iconSmall=0) { mIcon=iconLarge; mSmallIcon=iconSmall; return static_cast<optType&>(*this); }; // Specifies the icon, and optionally a small icon
// ...Many others removed...
};
template <class T>
class _createWindowOpts: public _sharedWindowOpts<T> {
public: ///////////////////////////////////////////////////////////////
_createWindowOpts() { };
// These can't be used with child windows, or aren't needed
optType& menu(HMENU m) { mMenuOrId=m; return static_cast<optType&>(*this); }; // Gives the window a menu
optType& owner(HWND hwnd) { mParentOrOwner=hwnd; return static_cast<optType&>(*this); }; // Sets the optional parent/owner
};
class createWindowOpts: public _createWindowOpts<createWindowOpts> {
public: ///////////////////////////////////////////////////////////////
createWindowOpts() { };
};
Funciona, pero como se puede ver, se requiere una notable cantidad de trabajo extra: un tipo de fundición del tipo de cambio de cada función, clases de plantilla adicionales, etcétera.
Mi pregunta es, ¿hay alguna manera más fácil de implementar el idioma de parámetros nominales en este caso, uno que no requiera todo el material extra?
Estoy de acuerdo, me preguntaba si alguien sabía de una forma más agradable de hacer las cosas en el código de la biblioteca. Gracias por el aporte. –