An Automated Setter Overloading Solution
The problems of Boost dependency, special support "gruff", "ingenious" code, and type checking leniency, can be solved by automating the generation of Options setter overloads, where the code generation macros directly generate the desired result -- an Options class -- and nothing more that the client code needs relate to:
//solution_using_automated_overloading.cpp
//
#include <iostream>
#include <progrock/cppx/collections/options.h>
struct AbstractButton
{
int hTextAlign;
CPPX_DEFINE_1OPTIONCLASS( Params, CPPX_OPTIONS_NO_BASE
, hTextAlign , int , 0
)
explicit AbstractButton( Params const& params = Params() )
: hTextAlign( params.hTextAlign() )
{}
};
struct CheckBox: AbstractButton
{
bool isAuto;
CPPX_DEFINE_1OPTIONCLASS( Params, AbstractButton::Params
, isAuto , bool , true
)
explicit CheckBox( Params const& params = Params() )
: AbstractButton( params )
, isAuto( params.isAuto() )
{}
};
void show( CheckBox const& cb )
{
using namespace std;
cout
<< boolalpha
<< "align = " << cb.hTextAlign << ", "
<< "isAuto = " << cb.isAuto << ".\n";
}
int main()
{
CheckBox widget1;
show( widget1 ); // 0, true (the default values)
CheckBox widget2( CheckBox::Params()
.hTextAlign( 1 )
);
show( widget2 ); // 1, true
CheckBox widget3( CheckBox::Params()
.hTextAlign( 1 )
.isAuto( false )
);
show( widget3 ); // 1, false
}
Here progrock is a namespace and directory that I use for my code in general. The [options.h] header, a pure header file module with nothing that needs separate compilation, supplies CPPX_DEFINE_nOPTIONCLASS macros with n from 1 to 9 inclusive. These macros support arbitrarily deep levels of options class derivation. The most that I've actually used has however been just four levels of options class derivation.
These macros are all that's needed in order to use this functionality, it's very simple to use: just invoke the appropriate macro for your number of options.
Why the Setter Generation Macros Can Be Annoying
As with the manual setters overloading approach the number of generated setter implementations is in a sense quadratic in the depth of class derivation, which might sound alarming -- uh oh, quadratic number of setters...
However, the depth of class derivation is usually small, like maximum four levels of derivation, and so, while "quadratic" does have some negative vibes this isn't a practical problem; it's the compiler that deals with it, and it deals well with it.
More practically, with the CPPX_DEFINE_nOPTIONCLASS macros, when you add or remove an option you have to update n accordingly. In contrast to the "quadratic" this might not seem to be a problem, it's just a few keystrokes. But a wrong n generally causes an avalanche of cryptic error messages, since like the BPAL the [options.h] header relies on templatization. And even though the first error message will tell you something about wrong number of arguments you might not realize that it's a wrong n, and thus waste some time, perhaps quite a lot of time. Plus, it's rather annoying to have to count things when the computer should excel at that task.


