My application requires end-users to write some classes to which I'll feed input data and take output data from. These user classes can be subclasses of a base class I provide. A way that's worked since the 90s would be a template allowing members to be declared as follows.
The initializer of the user class would pass in the object pointer to the constructor of these bindings. (Let's assume BaseClass has some vectors of pointers to such objects and the template adds the binding thingies to those vectors.)
class UserClass: public BaseClass {
UserClass() :
bi1( this ), bi2( this ), bi3( this ), bd1( this ), bd2( this )
{
}
BoundInput<int> bi1, bi2, bi3;
BoundOutput<double> bd1, bd2;
}
Later the base class would be able to populate bi1, bi2, bi3
with the initial data, and call the user function.
Then user code that receives these variables would have to write:
virtual void Process() {
int i1 = bi1.get(), i2 = bi2.get(), i3 = bi3.get();
double d1, d2;
// calculate d1 and d2 from i1, i2, i3
bd1.set( d1 );
bd2.set( d2 );
}
So the question is: how to avoid the end-user having to 1) use a special template like BoundInput<> etc., and instead just use the types they want; 2) pass this
into constructors, 3) avoid having to explicitly declare "regular" variables and explicitly get and set values.
My dream is that the end user can simply write the following:
class UserClass: public BaseClass {
UserClass()
{
BindInputs( i1, i2, i3 );
BindOutputs( d1, d2 );
}
int i1, i2, i3;
double d1, d2;
virtual void Process() {
// calculate d1 and d2 from i1, i2, i3
}
}
Then the framework could directly populate i1, i2, i3
before calling Process()
, and afterwards extract values from d1
and d2
.
I feel BindInputs()
and BindOutputs()
could be a function templates? with a class...
somehow... that uses class template argument deduction (CTAD) to figure out the first template?
(I won't know a priori what the inputs and outputs will be, so I don't think I can simply supply inputs as method parameters or have the function return an little struct of outputs. But if there's a way to do that that'd acceptable.)
Is there no way to make it just that simple, at least from the end-user's standpoint?
Bonus points if BindInputs()
and BindOutputs()
could easily be written WITHOUT the user class being a subclass of a specific base class... I can think of ways that could be fudged in single-threaded calling of initializers, using a global variable used by the BindInputs()
and Outputs()
functions, maintaining vectors of inputs and outputs in an object that points to the user object. Most methods would be fine, including variable argument macros and the like. I'd strongly prefer not using one that involved linear searches, hashes and so on, though.
BTW, I expect there would need to be per-template types in the background that can for instance take input from and send output to whatever the bound format is: a text stream, byte stream, SQL, whatever. I'd assume that end-users would have to write such classes for their own special types, and I'm fine with that being a little complicated but it has to be at least doable.