我不知道如何用你的方法做到這一點。
首先,asyncscanf函數的第三個參數沒有很好的類型。只有在asyncscanf主體中才可以接受(...)(函數的參數數量不限,並且不返回任何內容),但是接着傳遞給asyncscanf的參數應該是第三種類型,這可能是不可接受的。
其次,你必須按照格式(例如「iii」)來分配my_bytes。如果你有不同格式字符串的數量有限(這樣你就可以在所有可能的格式中「切換」)。但在一般情況下,我認爲這是不可能的。
但是因爲你用'variadic-templates'來標記你的問題,我假設你正在使用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);
}
注意有關代碼:
- 的想法是,我們有兩個參數包:一個不解析尚未參數和一個用於已解析的參數,並通過一個從第一組到第二傳遞參數之一;當所有參數被解析時,只需調用函數
- 如果您忘記專門爲asyncscanf編譯器會告訴您的作爲第三個參數傳遞的函數所需的類型解析函數。
- 由於在一個模板函數中使用兩個參數包時出現問題,我必須使用模板struct asyncscanf_helper和元組來代替簡單函數模板asyncscanf_helper。
- 我在asyncscanf_helper中使用了std :: function,因爲它更通用,你可以使用例如lambdas作爲參數,但是目前我將asyncscanf中的標準函數作爲參數類型保留,否則它的第二個參數必須顯式強制轉換爲具有適當簽名的std :: function,或者必須明確聲明模板參數。
- 由於解析函數專門化的假實現,如果您運行代碼但不會看到預期的結果,但由於解析不是您問題的一部分,所以我將它留給了嘲笑。
當你有原始類型時,你爲什麼需要'「iii」'? – Yakk
我不確定我是否明白你的觀點。你能否更深入地解釋這一點? –
您將'「iii」'傳遞給您的函數。爲什麼?'myfunc'的類型爲'function' - 爲什麼要傳遞一個具有該信息副本的字符串?爲何使用運行時數據? –
Yakk