0
$\begingroup$

I am working with C++ for a Teensy (Arduino-like board). There is a pattern that I have a lot which annoys me because it is tedious and ugly. But I don't know how to refactor it to make it less repetitive and prettier. Here's the code (in simplified form)

void Arm::armCommand(String command, float arg)
{
    if (command == "wrist")
    {
        wrist((int)arg);
    }
    if (command == "elbow")
    {
        elbow((int)arg);
    }

    if (command == "shoulder")
    {
        shoulder((int)arg);
    }
}
$\endgroup$
2
  • $\begingroup$ if your code works without error, then it belongs at codereview.stackexchange.com $\endgroup$
    – jsotola
    Jan 21 at 16:52
  • $\begingroup$ they may not know teensy c++ but sure ok. $\endgroup$
    – pitosalas
    Jan 21 at 17:23

2 Answers 2

0
$\begingroup$

Here's something that looks like it might be the direction you want to go: https://stackoverflow.com/questions/19473313/how-to-call-a-function-by-its-name-stdstring-in-c.

In summary, create a map between the string name and the function pointer, but here I'm assuming Teensy supports function pointers.

$\endgroup$
0
$\begingroup$

I had the same doubt on this.

Here is how I solved this doubt: https://github.com/ConradLiuuu/strategy-sample-cpp/blob/master/include/cart.hpp

In master branch, I wrote the code like you.
In refactor branch, I wrote the code with unordered_map to save the functions, user passes the argument into interface function to call regarding sub-function.

Go back to your case, the concept may like this. (I assume sub-function won't return a value)

I recommend you visit the link for more detail.
If you want to add new sub-functions in future, you only need to add static function and add it into unordered_map.

#include <unordered_map>
#include <functional>

using MyFunctionType = function<void(int)>;

// public methods
unordered_map<string, MyFunctionType> commandFuncs()
{
  unordered_map<string, MyFunctionType> my_dict;

  my_dict["wrist"] = callWrist;
  my_dict["elbow"] = callElbow;
  my_dict["shoulder"] = callShouder;

  return my_dict;
}

void armCommand(const string& command, float arg)
{
  auto dict = this->commandFuncs();
  auto it = dict.find(command);

  if (it != dict.end())
  {
    return it->second((int)arg);
  }
  else
  {
    throw invalid_argument("command is not exist");
  }
}

// private methods
static void callWrist(int arg)
{
  wrist(arg);
}

static void callElbow(int arg)
{
  elbow(arg);
}

static void callShoulder(int arg)
{
  shoulder(arg);
}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.