Problem Statement

For different reasons you might want to simplify the redundant task of writing C++ fields and the associated default getters and setters. In my particular case, I want to generate C++ fields and their setters so I can do introspection from my GSP framework. Placing myself as a user, my requirements are:

  • No modification of the build process should be necessary,
  • redundance in declaration should be minimal,
  • setters must be exported when we build a dynamic library.

Elements of Solution

  • Build transparency ⇒ I use preprocessor macros.
  • Minimal redundance ⇒ a single macro defines both the field and an inline implementation of the setter.
  • Forcing export in libraries ⇒ I use “virtual” inline methods for setters. This is the first (and only) way I found to force the export of the inline setter by gcc.

Result: The Macros

From a user point of view, here is an example usage:

// In the .h file (no constraint on the cpp, it might even not exist)
class CustomSource {
    FIELD_WITH_SETTER(int,   start,     setStart);
    FIELD_WITH_SETTER(int,   delta,     setDelta);
    FIELD_WITH_SETTER(float, threshold, setThreshold);
    STRING_FIELD_WITH_SETTER(url,       setUrl);
    STRING_FIELD_WITH_SETTER(outUrl,    setOutUrl);

The first proposed macros is totally generic. The second one is to declare a “string” (from C++ standard library) with a setter using a “char*”.

#define FIELD_WITH_SETTER(type,name,setName)                            \
    type name;                                                          \
    virtual void setName(type name) {this->name = name;}

#define STRING_FIELD_WITH_SETTER(name,setName)                          \
    std::string name;                                                   \
    virtual void setName(char* name) {this->name = name;}               

And for cases you also need getters.

#define FIELD_WITH_ACCESSORS(type,name,getName,setName)                 \
    type name;                                                          \
    virtual type getName()          {return name;}                      \
    virtual void setName(type name) {this->name = name;}                
Any feedback or remarks? Contact me at click-me ;-p