I am trying to offer users of my library to supply their own calculation functions, that need to maintain the rules:
- returns a
float
value - may require 0 to 7
float
arguments - no exceptions possible
I got a solution - see below - but it is bulky and ugly. I would bet there is a more elegant way to solve it with templates and type_traits, but I cannot wrap my head around it.
// Copyright 2022 bla
#include <cstdint>
#include <iostream>
#include <functional>
#include <math.h>
using std::cout;
using std::endl;
class D {
public:
using Dlambda0 = std::function<float()>;
using Dlambda1 = std::function<float(float)>;
using Dlambda2 = std::function<float(float, float)>;
using Dlambda3 = std::function<float(float, float, float)>;
using Dlambda4 = std::function<float(float, float, float, float)>;
using Dlambda5 = std::function<float(float, float, float, float, float)>;
using Dlambda6 = std::function<float(float, float, float, float, float, float)>;
using Dlambda7 = std::function<float(float, float, float, float, float, float, float)>;
D(const char *name, Dlambda0 dFn) : n(name), fn0 {std::move(dFn)} { cout << name << ":" << __PRETTY_FUNCTION__ << endl; arity = 0; }
D(const char *name, Dlambda1 dFn) : n(name), fn1 {std::move(dFn)} { cout << name << ":" << __PRETTY_FUNCTION__ << endl; arity = 1; }
D(const char *name, Dlambda2 dFn) : n(name), fn2 {std::move(dFn)} { cout << name << ":" << __PRETTY_FUNCTION__ << endl; arity = 2; }
D(const char *name, Dlambda3 dFn) : n(name), fn3 {std::move(dFn)} { cout << name << ":" << __PRETTY_FUNCTION__ << endl; arity = 3; }
D(const char *name, Dlambda4 dFn) : n(name), fn4 {std::move(dFn)} { cout << name << ":" << __PRETTY_FUNCTION__ << endl; arity = 4; }
D(const char *name, Dlambda5 dFn) : n(name), fn5 {std::move(dFn)} { cout << name << ":" << __PRETTY_FUNCTION__ << endl; arity = 5; }
D(const char *name, Dlambda6 dFn) : n(name), fn6 {std::move(dFn)} { cout << name << ":" << __PRETTY_FUNCTION__ << endl; arity = 6; }
D(const char *name, Dlambda7 dFn) : n(name), fn7 {std::move(dFn)} { cout << name << ":" << __PRETTY_FUNCTION__ << endl; arity = 7; }
float operator() () { return callForArity(0, nanf(""), nanf(""), nanf(""), nanf(""), nanf(""), nanf(""), nanf("")); }
float operator() (float a) { return callForArity(1, a, nanf(""), nanf(""), nanf(""), nanf(""), nanf(""), nanf("")); }
float operator() (float a, float b) { return callForArity(2, a, b, nanf(""), nanf(""), nanf(""), nanf(""), nanf("")); }
float operator() (float a, float b, float c) { return callForArity(3, a, b, c, nanf(""), nanf(""), nanf(""), nanf("")); }
float operator() (float a, float b, float c, float d) { return callForArity(4, a, b, c, d, nanf(""), nanf(""), nanf("")); }
float operator() (float a, float b, float c, float d, float e) { return callForArity(5, a, b, c, d, e, nanf(""), nanf("")); }
float operator() (float a, float b, float c, float d, float e, float f) { return callForArity(6, a, b, c, d, e, f, nanf("")); }
float operator() (float a, float b, float c, float d, float e, float f, float g) { return callForArity(7, a, b, c, d, e, f, g); }
protected:
const char *n;
Dlambda0 fn0;
Dlambda1 fn1;
Dlambda2 fn2;
Dlambda3 fn3;
Dlambda4 fn4;
Dlambda5 fn5;
Dlambda6 fn6;
Dlambda7 fn7;
uint8_t arity;
float callForArity(uint8_t givenArgs, float a, float b, float c, float d, float e, float f, float g) {
switch (arity) {
case 0:
return fn0();
break;
case 1:
return fn1(a);
break;
case 2:
return fn2(a, b);
break;
case 3:
return fn3(a, b, c);
break;
case 4:
return fn4(a, b, c, d);
break;
case 5:
return fn5(a, b, c, d, e);
break;
case 6:
return fn6(a, b, c, d, e, f);
break;
case 7:
return fn7(a, b, c, d, e, f, g);
break;
}
return nanf("");
}
};
float fix1(float a) {
return a * a;
}
int main(int argc, char **argv) {
// register some functions
D function("bla", { []() { return 5; }});
D function2("blubb", { [](float x, float y) { return x + y; }});
D function3("Blort", fix1);
cout << function() << endl; // Okay
cout << function2(1.0, 5.5) << endl; // Okay
cout << function2(5.5) << endl; // Aw!
cout << function3(5.5) << endl; // okay
return 0;
}