In our code, we have many functions that consume numerous const&
"configuration" parameters. Since C++ supports only positional arguments, we've decided to pass most of them in the form of a shared config dictionary (map). That is obviously short-sided, because as our code grew, we've lost track of which function consumes which arguments.
One of the ways out of the mess is to group the algorithms into many (potentially overlapping) structures, and pass the structures to the functions instead of the generic map. Some functions will still consume several such structures, though. To further reduce the confusion, we may introduce a convention, where the order of the passed structures is fixed (e.g. alphabetic), although that may feel unnatural for some use cases.
More flexible solution would be to let C++ decide the order itself:
Suppose we have a
struct ConfigParsA {
string somePath;
long numberOfIterations;
/*...*/
};
struct ConfigParsB {
/*...*/
};
struct ConfigParsC {
/*...*/
};
struct Result {
/*...*/
}
Result functionThatUsesLotsOfArguments(long l1, const std::vector<int>& v1, const ConfigParsA& p1, const ConfigParsB& p2, const ConfigParsC& c3);
void main() {
ConfigPars1 par1{"/home/user/file.csv", 1000, /*...*/};
ConfigPars2 par2{/*...*/};
ConfigPars3 par3{/*...*/};
std::vector<int> vec{1,2,3,4};
auto result = functionThatUsesLotsOfArguments(42, vec, par2, par3, par1); //Compile error: order of parameters is wrong.
};
I am thinking, that maybe there is an elegant solution to let the following code to compile:
void main() {
ConfigPars1 par1{"/home/user/file.csv", 1000, /*...*/};
ConfigPars2 par2{/*...*/};
ConfigPars3 par3{/*...*/};
std::vector<int> vec{1,2,3,4};
auto curried_f = curry(functionThatUsesLotsOfArguments)(42, vec)
auto result = callWithAnyOrderOfParameters(curried_f, par2, par3, par1);
};
I definitely value code simplicity and hate excessive template meta-programming, so I am not really OK with 100+ loc of template code being added to the project just to allow this trick. Maybe it is possible to pull it off relatively easily? Currying is relatively nicely solved (How can currying be done in C++?), so I wonder if there's a way to implement the callWithAnyOrderOfParameters
.
Assumptions:
functionThatUsesLotsOfArguments
has no overloads.- Each argument has a distinct, non-convertible type.