使用variadic模板的C 通用命令解析器

C++ Generic command parser using variadic templates

本文关键字:命令 variadic 使用      更新时间:2023-10-16

我正在尝试编写某种命令处理程序,该命令处理程序可以使istringstreams化,自动将令牌自动转换为特定类型的变量,并以转换变量为参数调用回调函数。这是我的代码的简化版本:

void Callback(int x, char y, float z) {
  // do whatever
  // note: For simplicity, I use a callback with a fixed signature
  //       here. In my actual implementation, the callback can be
  //       called with any number and types of arguments - but that
  //       I have solved already.
}
template<typename T>
T GetNextArgument(std::istringstream& strm) {
  // get one token from the input stream and convert it to the required type
  T val;
  strm >> val;
  return val;
}
template<typename ...Args>
void ParseAndExecute(std::istringstream& input_stream) {
  Callback(GetNextArgument<Args>(input_stream)...);
}
int main() {
  std::istringstream strm("15 a 17.3");
  ParseAndExecute(strm);
  return 0;
}

我遇到的问题是,参数包扩展后的ParseAndExecute()功能如下:

void ParseAndExecute(std::istringstream& strm) {
  Callback(GetNextArgument<int>(strm), 
           GetNextArgument<char>(strm),
           GetNextArgument<float>(strm));
}

由于未定义对参数的评估顺序,因此代币可以以不正确的顺序从流中获取(在我的情况下,它们始终是)。相反,我需要扩展才能给我更多类似的东西:

void ParseAndExecute(std::istringstream& strm) {
  int a1 = GetNextArgument<int>(strm);
  char a2 = GetNextArgument<char>(strm);
  float a3 = GetNextArgument<float>(strm);
  Callback(a1, a2, a3);
}

,但我看不到如何通过参数包扩展来实现这一目标。也许有一个递归模板...?还是您还有其他建议以实现类似的功能?

struct Caller {
    template<class...Args>
    Caller(Args&&... args) { Callback(std::forward<Args>(args)...); }
};
template<typename ...Args>
void ParseAndExecute(std::istringstream& input_stream) {
  Caller{GetNextArgument<Args>(input_stream)...};
}

您可以使用带有列表初始化的中间std::tuple,因为在这种情况下是必须的:

std::tuple<Args...> tuple_args = {GetNextArgument<Args>(input_stream)... };
std::apply([](auto&&... args) { 
    Callback(std::forward<decltype(args)>(args)... );
 }, std::move(tuple_args));

,如果Callback没有您提到的固定签名,则必须使用lambda。