As an example, I have the following function template:
template <typename X, typename Y, typename Z>
void f(X &x, Y &y, Z &z) { ... }
I need to write a user interface in the form of
void fxyz(std::string optionX, std::string optionY, std::string optionZ)
Here, optionX
, optionY
, optionZ
can be "x1" or "x2"
, "y1" or "y2"
, "z1" or "z2"
respectively. Every option corresponds to a different type, i.e., X1
, X2
, Y1
, ... .Currently I implemented it like this:
template <typename Y, typename Z>
void fx(std::string &optionX, Y &y, Z &z)
{
if (optionX == "x1") {
X1 x; f <X1, Y, Z> (x, y, z); }
else {
X2 x; f <X2, Y, Z> (x, y, z); }
}
template <typename Z>
void fxy(std::string &optionX, std::string &optionY, Z &z)
{
if (optionY == "y1") {
Y1 y; fx <Y1, Z> (optionX, y, z); }
else {
Y2 y; fx <Y2, Z> (optionX, y, z); }
}
void fxyz(std::string &optionX, std::string &optionY, std::string &optionZ)
{
if (optionZ == "z1") {
Z1 z; fxy <Z1> (optionX, optionY, z); }
else {
Z2 z; fxy <Z2> (optionX, optionY, z); }
}
This seems a lot of work especially if there are more template parameters. Any easier way to achieve what I want?
Thanks!
CodePudding user response:
Map into variant
s, then visit
them.
std::variant<X1, X2> choose_X(std::string_view choice) {
if(choice == "x1") return X1();
else if(choice == "x2") return X2();
}
std::variant<Y1, Y2> choose_Y(std::string_view choice) {
if(choice == "y1") return Y1();
else if(choice == "y2") return Y2();
}
std::variant<Z1, Z2> choose_Z(std::string_view choice) {
if(choice == "z1") return Z1();
else if(choice == "z2") return Z2();
}
You are not getting out of writing some set of rules to get from strings to objects, of course. A possible variation is
std::map<std::string, std::function<std::variant<X1, X2>()>> choices_X{
{"x1", []() { return X1(); }},
{"x2", []() { return X2(); }}
};
Then simply
std::string choice_X, choice_Y, choice_Z;
std::visit(
[](auto&&... xs) -> decltype(auto) { return f(std::forward<decltype(xs)>(xs)...); },
choose_X(choice_X), choose_Y(choice_Y), choose_Z(choice_Z)
);
O(n^2) code length is now O(n) code length (in number of parameters).