我不知道如何用你的方法做到这一点。
首先,asyncscanf 函数的第三个参数没有好的类型。在 asyncscanf 主体中只能接受 void(...) (函数采用无限数量的参数并且不返回任何内容),但是您传递给 asyncscanf 的参数应该是可能不可接受的类型。
其次,您必须根据格式(例如“iii”)发送 my_bytes。如果您有有限数量的不同格式字符串,则可以这样做(然后您可以“切换”所有可能的格式)。但在一般情况下,我认为它无法完成。
但是因为您使用“可变模板”标记您的问题,所以我假设您使用的是 C++11/14。
也许您想让 asyncscanf 的格式参数成为更具可读性的模板参数(我假设格式在编译时总是已知的)。低于解决方案的sn-p。
#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);
}
关于代码的注释:
- 想法是我们有两个参数包:一个用于尚未解析的参数,一个用于已解析的参数,并从第一个包到第二个包一个接一个地传递参数;解析完所有参数后,只需调用函数
- 如果您忘记为作为第三个参数传递给 asyncscanf 的函数所需的类型专门分析函数,编译器会告诉您这一点。
- 我不得不使用模板 struct asyncscanf_helper 和元组,而不是简单的函数模板 asyncscanf_helper,因为在一个模板函数中使用两个参数包存在问题。
- 我在 asyncscanf_helper 中使用了 std::function,因为它更通用,您可以使用例如lambdas 作为您的参数,但目前我将 asyncscanf 中的标准函数保留为参数类型,因为否则它的第二个参数必须显式转换为具有适当签名的 std::function 或必须显式声明模板参数。
- 由于 parse 函数特化的虚假实现,如果您运行代码,您将看不到预期的结果,但因为解析不是您的问题的一部分,所以我将其搁置。