Home > Back-end >  Easiest way to deduce templates
Easiest way to deduce templates

Time:08-25

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 variants, 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).

  • Related