Estoy creando mi propia implementación de XUL en C++ utilizando la API de Windows. El hecho de que los elementos sean construidos por el analizador XML requiere que tengan interfaces idénticas, de modo que no es necesario escribir código personalizado para cada constructor de elementos. El resultado es que la mayoría de mis elementos se ven así:D.R.Y frente a "evitar macros"
class Button : public Element
{
public:
static const char * Type() { return "button"; }
private:
friend class Element;
Button(Element * inParent, const AttributesMapping & inAttributesMapping);
};
class Label : public Element
{
public:
static const char * Type() { return "label"; }
private:
friend class Element;
Label(Element * inParent, const AttributesMapping & inAttributesMapping);
};
class Description : public Element
{
public:
static const char * Type() { return "description"; }
virtual bool init();
private:
friend class Element;
Description(Element * inParent, const AttributesMapping & inAttributesMapping);
};
Aquí hay mucha duplicación de código. Me pregunto si sería una buena idea para reemplazarlos con las llamadas macro como esta:
#define DECLARE_ELEMENT(ElementType, XULName) \
class ElementType : public Element \
{ \
public: \
static const char * Type() { return XULName; } \
\
private: \
friend class Element; \
ElementType( \
Element * inParent, \
const AttributesMapping & inAttributesMapping); \
}; \
DECLARE_ELEMENT(Window, "window")
DECLARE_ELEMENT(Button, "button")
DECLARE_ELEMENT(Label, "label")
no he trabajado por completo el concepto todavía, así que algunas cosas que faltan aquí, al igual que las definiciones de clases, y (tal vez) la capacidad de agregar métodos por elemento.
Pero me gustaría saber su opinión sobre el uso de macros en esta situación. Siéntete libre de compartir tus pensamientos.
EDITAR
Ahora estoy usando un pequeño script Ruby que genera los archivos de origen y de cabecera de un conjunto de plantillas. Mejoré los scripts para que los archivos también se marquen automáticamente para agregarlos en SVN, y el archivo de proyecto de Visual Studio se modifique para incluir los archivos. Esto me ahorra mucho trabajo manual. Estoy bastante feliz con esta solución. FYI esto es lo que las plantillas ven ahora:
#ifndef {{ELEMENT_NAME_UPPER}}_H_INCLUDED
#define {{ELEMENT_NAME_UPPER}}_H_INCLUDED
#include "XULWin/Element.h"
namespace XULWin
{
class {{ELEMENT_NAME}} : public Element
{
public:
static ElementPtr Create(Element * inParent, const AttributesMapping & inAttr)
{ return Element::Create<{{ELEMENT_NAME}}>(inParent, inAttr); }
static const char * Type() { return "{{ELEMENT_TYPE}}"; }
virtual bool init();
private:
friend class Element;
{{ELEMENT_NAME}}(Element * inParent, const AttributesMapping & inAttributesMapping);
};
} // namespace XULWin
#endif // {{ELEMENT_NAME_UPPER}}_H_INCLUDED
CPP documento:
#include "XULWin/{{ELEMENT_NAME}}.h"
#include "XULWin/{{ELEMENT_NAME}}Impl.h"
#include "XULWin/AttributeController.h"
#include "XULWin/Decorator.h"
namespace XULWin
{
{{ELEMENT_NAME}}::{{ELEMENT_NAME}}(Element * inParent, const AttributesMapping & inAttributesMapping) :
Element({{ELEMENT_NAME}}::Type(),
inParent,
new {{ELEMENT_NAME}}Impl(inParent->impl(), inAttributesMapping))
{
}
bool {{ELEMENT_NAME}}::init()
{
return Element::init();
}
} // namespace XULWin
Apoyo DRY. hacer las cosas más limpias – mauris
Uso macros principalmente para evitar * símbolo * repeticiones en uno o dos líneas. Un muro '# define' como el suyo a menudo se puede resolver a una función/plantilla auxiliar y, a veces, a una macro de declaración simpel. MartinB ha demostrado una buena solución para su caso, ni siquiera necesita una macro. – peterchen
¿Por qué no estás haciendo la versión de la plantilla? – GManNickG