C++如何将字符串键映射到特定对象的类方法调用?

发布于 2025-02-11 21:35:04 字数 970 浏览 0 评论 0原文

在C ++中,我试图将用户提供的字符串映射到特定对象的类方法调用。我成功地将用户提供的字符串映射到为另一个应用程序的功能调用,但是我不知道如何将这种方法扩展到用于为特定对象调用的类方法的工作。我将非常感谢任何帮助确定如何修复有缺陷的尝试实施的帮助:

void read_input(std::string& input_filename, Class_Name& my_object)
{
  // Map string keys to object member invocation
  std::map<const std::string, std::function<void (const std::string&)>> argument_map =
  {
    {"input_one", my_object.method_one},
    {"input_two", my_object.method_two},
    {"input_three", my_object.method_three}
  };

  std::ifstream input_file;
  input_file.open(input_filename);
  std::string line;
  while (input_file)
  {
    std::getline (input_file, line);
    std::stringstream argument_read(line);
    std::string command;
    std::string tmp;
    argument_read >> command;
    if (command[0] - '#' == 0) continue;
    while (argument_read >> tmp)
    {
      if (tmp[0] - '#' == 0) break;
      argument_map[command](tmp);
    }
  }
  return;
}

In C++, I am trying to map a user-provided string to a class method invocation for a specific object. I was successful in mapping user-provided strings to function calls for another application, but I do not know how to extend this approach to work for class methods being invoked for a particular object. I would greatly appreciate any assistance in determining how to fix my attempted implementation that is flawed:

void read_input(std::string& input_filename, Class_Name& my_object)
{
  // Map string keys to object member invocation
  std::map<const std::string, std::function<void (const std::string&)>> argument_map =
  {
    {"input_one", my_object.method_one},
    {"input_two", my_object.method_two},
    {"input_three", my_object.method_three}
  };

  std::ifstream input_file;
  input_file.open(input_filename);
  std::string line;
  while (input_file)
  {
    std::getline (input_file, line);
    std::stringstream argument_read(line);
    std::string command;
    std::string tmp;
    argument_read >> command;
    if (command[0] - '#' == 0) continue;
    while (argument_read >> tmp)
    {
      if (tmp[0] - '#' == 0) break;
      argument_map[command](tmp);
    }
  }
  return;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

离鸿 2025-02-18 21:35:04

由于所有方法都属于同一类并且具有相同的签名,因此您可以使用对成员函数的指针,使用成员访问 operator。 * 呼叫它们(no std :: function需要),例如:

void read_input(std::string& input_filename, Class_Name& my_object)
{
  // Map string keys to object member invocation
  using method_type = void (Class_Name::*)(const std::string&);
  static const std::map<std::string, method_type> argument_map =
  {
    {"input_one",   &Class_Name::method_one},
    {"input_two",   &Class_Name::method_two},
    {"input_three", &Class_Name::method_three}
  };

  std::ifstream input_file(input_filename);
  std::string line;
  while (std::getline (input_file, line))
  {
    std::istringstream argument_read(line);
    std::string command, param;
    if (argument_read >> command && command[0] != '#')
    {
      auto iter = argument_map.find(command);
      if (iter != argument_map.end())
      {
        method_type method = iter->second;
        while (argument_read >> param && param[0] != '#')
          (my_object.*method)(param);
      }
    }
  }
}

否则,您可以使用 std :: bind() with std :: function,例如:

void read_input(std::string& input_filename, Class_Name& my_object)
{
  // Map string keys to object member invocation
  using std::placeholders::_1;
  using function_type = std::function<void (const std::string&)>;
  std::map<std::string, function_type> argument_map =
  {
    {"input_one",   std::bind(&Class_Name::method_one, &my_object, _1) }
    {"input_two",   std::bind(&Class_Name::method_two, &my_object, _1) },
    {"input_three", std::bind(&Class_Name::method_three, &my_object, _1) }
  };

  std::ifstream input_file(input_filename);
  std::string line;
  while (std::getline (input_file, line))
  {
    std::istringstream argument_read(line);
    std::string command, param;
    if (argument_read >> command && command[0] != '#')
    {
      auto iter = argument_map.find(command);
      if (iter != argument_map.end())
      {
        auto &func = iter->second;
        while (argument_read >> param && param[0] != '#')
          func(param);
      }
    }
  }
}

或,您可以使用 lambdas 带有std :: function :: function,例如:

void read_input(std::string& input_filename, Class_Name& my_object)
{
  // Map string keys to object member invocation
  using function_type = std::function<void (const std::string&)>;
  std::map<std::string, function_type> argument_map =
  {
    {"input_one",   [&](const std::string& s){ my_object.method_one(s); } },
    {"input_two",   [&](const std::string& s){ my_object.method_two(s); } },
    {"input_three", [&](const std::string& s){ my_object.method_three(s); } }
  };

  std::ifstream input_file(input_filename);
  std::string line;
  while (std::getline (input_file, line))
  {
    std::istringstream argument_read(line);
    std::string command, param;
    if (argument_read >> command && command[0] != '#')
    {
      auto iter = argument_map.find(command);
      if (iter != argument_map.end())
      {
        auto &func = iter->second;
        while (argument_read >> param && param[0] != '#')
          func(param);
      }
    }
  }
}

Since all of the methods belong to the same class, and have the same signature, you can use Pointers to member functions, using the member access operator.* to call them (no std::function needed), eg:

void read_input(std::string& input_filename, Class_Name& my_object)
{
  // Map string keys to object member invocation
  using method_type = void (Class_Name::*)(const std::string&);
  static const std::map<std::string, method_type> argument_map =
  {
    {"input_one",   &Class_Name::method_one},
    {"input_two",   &Class_Name::method_two},
    {"input_three", &Class_Name::method_three}
  };

  std::ifstream input_file(input_filename);
  std::string line;
  while (std::getline (input_file, line))
  {
    std::istringstream argument_read(line);
    std::string command, param;
    if (argument_read >> command && command[0] != '#')
    {
      auto iter = argument_map.find(command);
      if (iter != argument_map.end())
      {
        method_type method = iter->second;
        while (argument_read >> param && param[0] != '#')
          (my_object.*method)(param);
      }
    }
  }
}

Otherwise, you can use std::bind() with std::function, eg:

void read_input(std::string& input_filename, Class_Name& my_object)
{
  // Map string keys to object member invocation
  using std::placeholders::_1;
  using function_type = std::function<void (const std::string&)>;
  std::map<std::string, function_type> argument_map =
  {
    {"input_one",   std::bind(&Class_Name::method_one, &my_object, _1) }
    {"input_two",   std::bind(&Class_Name::method_two, &my_object, _1) },
    {"input_three", std::bind(&Class_Name::method_three, &my_object, _1) }
  };

  std::ifstream input_file(input_filename);
  std::string line;
  while (std::getline (input_file, line))
  {
    std::istringstream argument_read(line);
    std::string command, param;
    if (argument_read >> command && command[0] != '#')
    {
      auto iter = argument_map.find(command);
      if (iter != argument_map.end())
      {
        auto &func = iter->second;
        while (argument_read >> param && param[0] != '#')
          func(param);
      }
    }
  }
}

Or, you can use lambdas with std::function, eg:

void read_input(std::string& input_filename, Class_Name& my_object)
{
  // Map string keys to object member invocation
  using function_type = std::function<void (const std::string&)>;
  std::map<std::string, function_type> argument_map =
  {
    {"input_one",   [&](const std::string& s){ my_object.method_one(s); } },
    {"input_two",   [&](const std::string& s){ my_object.method_two(s); } },
    {"input_three", [&](const std::string& s){ my_object.method_three(s); } }
  };

  std::ifstream input_file(input_filename);
  std::string line;
  while (std::getline (input_file, line))
  {
    std::istringstream argument_read(line);
    std::string command, param;
    if (argument_read >> command && command[0] != '#')
    {
      auto iter = argument_map.find(command);
      if (iter != argument_map.end())
      {
        auto &func = iter->second;
        while (argument_read >> param && param[0] != '#')
          func(param);
      }
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文