Я не знаю, как это сделать с вашим подходом.
Во-первых, нет подходящего типа для третьего параметра функции asyncscanf. В теле asyncscanf допустимо только значение void(...) (функция принимает неограниченное количество аргументов и ничего не возвращает), но тогда аргумент, который вы передаете asyncscanf в качестве третьего, должен быть того типа, который, вероятно, неприемлем.
Во-вторых, вы должны выполнить отправку my_bytes в соответствии с форматом («iii» в примере). Это можно сделать, если у вас есть конечное количество строк различных форматов (тогда вы можете «переключаться» между всеми возможными форматами). Но в общем случае я полагаю, что это невозможно сделать.
Но поскольку вы отмечаете свой вопрос «вариативными шаблонами», я предполагаю, что вы используете С++ 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);
}
Примечания к коду:
- идея в том, что у нас есть два пакета параметров: один для еще не проанализированных параметров и один для уже проанализированных параметров и параметры передаются по одному из первого пакета во второй; когда все параметры проанализированы, просто вызовите функцию
- если вы забудете специализировать функцию синтаксического анализа для типа, необходимого функции, переданной в качестве третьего аргумента, компилятор asyncscanf сообщит вам об этом.
- Мне пришлось использовать структуру шаблона asyncscanf_helper и кортежи вместо простого шаблона функции asyncscanf_helper из-за проблем с использованием двух пакетов параметров в одной функции шаблона.
- Я использовал std::function в asyncscanf_helper, потому что он более общий, и вы можете использовать, например. lambdas в качестве ваших аргументов, но на данный момент я оставляю стандартную функцию в asyncscanf в качестве типа параметра, потому что в противном случае ее второй аргумент должен быть явно приведен к std::function с соответствующей подписью или параметры шаблона должны быть указаны явно.
- Из-за фальшивой реализации специализаций функций синтаксического анализа вы не увидите ожидаемых результатов, если запустите код, но поскольку синтаксический анализ не был частью вашего вопроса, я оставил его высмеянным.
person
robal
schedule
03.01.2015
"iii"
, когда у вас есть исходные типы? - person Yakk - Adam Nevraumont   schedule 03.01.2015"iii"
своей функции. Почему?myfunc
имеет типfunction<void(int,int,int)>
-- зачем передавать строку с дубликатом этой информации? Зачем использовать данные времени выполнения? - person Yakk - Adam Nevraumont   schedule 04.01.2015int read_int(byte*&)
? Или что-то эквивалентное? (синхронное чтение из байтов в одно значение, в этом случае обновляет ввод после прочитанных данных). В этом много шаблонов и много решений, и я думаю, что в основном они не связаны с вашей проблемой. - person Yakk - Adam Nevraumont   schedule 04.01.2015