c++ - 如何将可变数量和类型的参数传递给模板函数?

标签 c++ templates visual-studio-2012 args variadic

我正在设置一个控制台命令,它接受可变数量的参数,每个参数都可以是基本类型(int、float、bool、string),然后将它们传递给一个具有 8 个重载以支持不同类型的函数不同类型的参数数量。我如何根据类型将命令行字符串解析为值,然后将它们传递给函数?

我可以通过函数 const char* GetArg(int index) 检索每个参数。将 char* 转换为正确的类型不是问题,所以不用担心这部分。存储值并以某种方式传递给模板函数是我坚持的部分。

例如,如果使用以下字符串执行命令:"command 66 true 5 "string value"0.56"

然后它将被分解成以下参数并以某种方式存储:

int arg1 = GetArg(1); // 66
bool arg2 = GetArg(2); // true
int arg3 = GetArg(3); // 5
char* arg4 = GetArg(4); // "string value"
float arg5 = GetArg(5); // 0.56

然后根据参数的个数,调用正确的模板函数:

// The function definition looks something like this:
void SomeFunc();
template<typename T1>
void SomeFunc(const T1& arg1);
template<typename T1, typename T2>
void SomeFunc(const T1& arg1, const T2& arg2);
// etc...

// And then somehow it would be called. This is just an example. I don't
// know how to call it in a way that would work with variable number and
// type of args.
switch (argCount)
{
case 0:
    SomeFunc();
    break;
case 1:
    SomeFunc(arg1);
    break;
case 2:
    SomeFunc(arg1, arg2);
    break;
case 3:
    SomeFunc(arg1, arg2, arg3);
    break;
case 4:
    SomeFunc(arg1, arg2, arg3, arg4);
    break;
case 5:
    SomeFunc(arg1, arg2, arg3, arg4, arg5);
    break;
}

您将如何使这成为可能?以某种可以传递给模板函数的方式存储参数,以便它知道每个参数的类型似乎不太可能,但我觉得我只是没有想到什么。

我也无法更改此界面。这是我必须处理的第三方功能。所以不管怎么实现,最终还是要经过SomeFunc()

重要提示:我在 Visual Studio 2012 中执行此操作,因此我对较新的 C++ 功能相当有限。它可以做一点 C++11,但仅此而已。尝试将项目升级到更新的版本,但现在这是我必须处理的问题。

最佳答案

using basic_type = std::variant<int, float, bool, std::string>;

using flat_arguments = std::vector<basic_type>;

template<std::size_t...Ns>
using packed_arguments = std::variant< std::array<basic_type, Ns>... >;

template<class T, std::size_t...Ns>
std::array<T, sizeof...(Ns)> pack_one( std::vector<T> n, std::index_sequence<Ns...> ) {
  return {{ std::move(n[Ns])... }};
}

template<class T, std::size_t...Ns>
std::optional<std::variant< std::array<T, Ns>... >>
pack_all(std::vector<T> n, std::index_sequence<Ns...> ) {
  std::optional<std::variant< std::array<T, Ns>... >> retval;
  if (n.size() >= sizeof...(Ns)) { return retval; }
  (
    (
      (n.size()==Ns)?
        void(retval.emplace( pack_one( std::move(n), std::make_index_sequence<Ns>{} ):
        void()
    ),...
  );
  return retval;
}

flat_arguments get_arguments( int argc, char const* const*argv); // write this

auto invoke_somefunc = [](auto&&...args){
  return SomeFunc( decltype(args)(args)... );
};

int main(int argc, char const*const* argv) {
  auto args = get_arguments(argc, argv);
  auto args_packed = pack_all(std::move(args), std::make_index_sequence<9>{} );
  if (!args_packed) return -1;
  std::visit( [](auto&& args){
    std::apply( [](auto&&...args){
      std::visit( invoke_somefunc, args... );
    }, args );
  }, args_packed );
}

应该这样做。可能包含错别字。 .

boost 具有等效类型(variantoptional),可以替换上面使用的 std,其中一些调整。

折叠包扩展可以用 中的数组扩展 hack 替换或更大。

关于c++ - 如何将可变数量和类型的参数传递给模板函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46818159/

相关文章:

C++ - 非局部静态对象与局部静态对象

c++ - C/C++ 优化检查以查看之前是否已经运行过函数

javascript - 使用铁路由器后 meteor 模板助手不工作

java - 强制 Eclipse 自动导入具有多个选项的类

php - 使用 php 发送带有模板的电子邮件

wpf - XAML 主题 Visual Studio 2012

c++ - 将 AVPackets 混合到 mp4 文件中

c++ - 内联函数机制

c# - 使用 Workflow 的 ASP.net 页面导航

asp.net - Visual Studio - 调试给出错误 0x800700b7