简体   繁体   English

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

[英]How to pass a variable number and type of arguments to template function?

I'm setting up a console command that takes a variable number of arguments, each of which can be basic types (int, float, bool, string) and then pass them to a function that has 8 overloads for supporting a different number of arguments of varying types. 我正在设置一个控制台命令,该命令接受可变数量的参数,每个参数可以是基本类型(int,float,bool,string),然后将它们传递给具有8个重载的函数,以支持不同数量的参数不同的类型。 How would I parse the command line string into values based on their type and then pass them to the function? 如何将命令行字符串根据其类型解析为值,然后将其传递给函数?

I can retrieve each argument via the function const char* GetArg(int index) . 我可以通过函数const char* GetArg(int index)检索每个参数。 Converting the char* to the proper type isn't an issue so don't worry about that part. char*转换为正确的类型不是问题,因此不必担心该部分。 Storing the values and somehow passing to the template function is the part I'm stuck on. 存储值并以某种方式传递给模板功能是我要坚持的部分。

For example, if the command was executed with the following string: "command 66 true 5 "string value" 0.56" 例如,如果命令使用以下字符串执行:“命令66 true 5”字符串值“ 0.56”

It would then be broken up into the following args and stored somehow: 然后将其分解为以下args并以某种方式存储:

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

And then based on the number of args, call the correct template function: 然后根据args的数量,调用正确的模板函数:

// 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;
}

How would you make this possible? 您将如何做到这一点? Storing the args in some way that can be passed to the template function so that it knows the type of each argument doesn't seem possible, but I feel like I'm just not thinking of something. 以某种可以传递给模板函数的方式存储args,以便它似乎无法知道每个参数的类型,但是我觉得我只是在想什么。

I can't change this interface either. 我也不能更改此界面。 This is a third party function that I just have to deal with. 这是我只需要处理的第三方功能。 So no matter how it is implemented, eventually it has to go through SomeFunc() . 因此,无论如何实现,最终都必须通过SomeFunc()

IMPORTANT: I'm doing this in Visual Studio 2012 so I'm rather limited on newer C++ features. 重要说明:我正在Visual Studio 2012中执行此操作,因此我相当受限于新的C ++功能。 It can do a little bit of C++11 but that's it. 它可以做一点C ++ 11,仅此而已。 Trying to upgrade the project to a newer version but for now that's what I have to deal with. 尝试将项目升级到新版本,但是现在这是我必须处理的。

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 );
}

that should do it. 应该这样做。 Probably contains typos. 可能包含错别字。 .

boost has equivalent types ( variant and optional ) that could replace the std use above, with some tweaks. boost具有等效的类型( variantoptional ),可以通过一些调整来替换上面的std用法。

The fold pack expansion can be replaced with the expand-in-array hack in or greater. fold pack扩展可以用或更高版本中的expand-in-array hack代替。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将可变数量的参数传递给lambda函数 - How to pass variable number of arguments to lambda function 如何将任意数量的 arguments 传递给 C++ 模板 function? - How to pass any number of arguments to C++ template function? 如何传递具有可变参数作为模板参数的成员函数? - How to pass a member function which has variable arguments as template argument? 如何将可变数量的参数从一个函数传递到另一个函数? - How to pass variable number of arguments from one function to another? 将可变数量的参数传递给别名函数 - Pass a variable number of arguments to an aliased function 如何将可变数量的参数传递给printf / sprintf - How to pass variable number of arguments to printf/sprintf 如何传递方法并使用可变编号 arguments 调用它 - How to pass method and call it with variable number of arguments 如何将覆盖传递给结构模板类型或将变量模板类型传递给函数? - How can I pass a override to a struct template type or variable template type to a function? 如何使用可变参数模板参数保存可变数量的参数? - How to save variable number of arguments using variadic template arguments? 将接受任意数量和类型的参数的函数作为类模板参数传递 - Passing a function that accepts any number and type of arguments as a class template argument
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM