C ++中的可变参数函数允许用户使用任意数量的参数调用函数。例如,sscanf将要解析的字符串,格式字符串和一组参数作为输入,这些参数将获取已解析项的值。 如果我想让这个范例异步怎么办?我需要解析一些数据,从某些字节中提取可变数量的参数。需要提取的参数以sscanf中的格式字符串指定。我希望我的函数可以这样调用:
function <void (int, int, int)> myfunc = [=] (int a, int b, int c)
{
// Do something here!
};
asyncsscanf(my_bytes, "iii", myfunc);
asyncsscanf应该执行所需的处理,完成后我希望它使用格式字符串中指定的正确参数调用myfunc。 有可能做这样的事吗?
谢谢
答案 0 :(得分:3)
我不知道如何用你的方法来做。
首先,asyncscanf函数的第三个参数没有好的类型。只有在asyncscanf体中可以接受的是void(...)(函数接受无限数量的参数并且不返回任何内容),但是然后传递给asyncscanf作为第三个的参数应该是那种类型,这可能是不可接受的。
其次,您必须根据格式(&#34; iii&#34;示例)来调度my_bytes。如果您拥有有限数量的不同格式字符串(然后您可以“切换所有可能的格式”),就可以完成此操作。但总的来说,我认为不能这样做。
但是因为你用&#39; variadic-templates&#39;标记了你的问题。我假设你使用的是C ++ 11/14。 也许你想让asyncscanf的格式参数成为一个更具可读性的模板参数(我假设格式在编译时总是知道的)。下面的解决方案片段。
#include <functional>
#include <iostream>
// template parsing function, remaining_bytes parameter should contain pointer to not parsed part
// of my_bytes
template <typename return_type> return_type parse(const char *my_bytes, const char *&remaining_bytes);
// specialization of parsing function for desired types, fake implementation
template <> int parse<int>(const char *my_bytes, const char *&remaining_bytes) {
remaining_bytes = my_bytes;
return 0;
}
// specialization of parsing function for desired types, fake implementation
template <> long parse<long>(const char *my_bytes, const char *&remaining_bytes) {
remaining_bytes = my_bytes;
return 1;
}
// declare helper template for general case
template <typename to_be_parsed_tuple, typename parsed_tuple>
struct asyncscanf_helper;
// all params parsed case
template <typename... parsed_params>
struct asyncscanf_helper<std::tuple<>, std::tuple<parsed_params...>> {
void operator()(const char *, std::function<void(parsed_params...)> fun, parsed_params... params) {
fun(params...);
}
};
// some params to be parsed case
template <typename first_param_to_be_parsed, typename...to_be_parsed_params, typename... parsed_params>
struct asyncscanf_helper<std::tuple<first_param_to_be_parsed, to_be_parsed_params...>, std::tuple<parsed_params...>> {
void operator()(const char *my_bytes, std::function<void(parsed_params..., first_param_to_be_parsed, to_be_parsed_params...)> fun, parsed_params... params) {
const char *remaining_bytes = 0;
first_param_to_be_parsed p1 = parse<first_param_to_be_parsed>(my_bytes, remaining_bytes);
asyncscanf_helper<std::tuple<to_be_parsed_params...>, std::tuple<parsed_params..., first_param_to_be_parsed>>()(remaining_bytes, fun, params..., p1);
}
};
template <typename... params>
void asyncscanf(const char *my_bytes, void function(params...)) {
asyncscanf_helper<std::tuple<params...>, std::tuple<>>()(my_bytes, function);
}
void test_fun(int a, int b, int c) {
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
}
void test_fun2(int a, long b, int c) {
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
}
int main() {
asyncscanf("1 2 3", test_fun);
asyncscanf("1 2 3", test_fun2);
}
关于代码的注释: