У меня есть несколько обратных вызовов, которые требуют, чтобы в подписи было int argc, char* argv[]
, но я хотел бы использовать std::span
и иметь специализацию шаблона для других вариантов, которым не нужны все аргументы.
#include <iostream>
#include <span>
using callback_t = auto(void* data, int argc, char* argv[]) -> int;
extern auto foo_register_callback(char const*, callback_t) -> int;
namespace foo {
using args = std::span<char* const, std::dynamic_extent>;
template<auto func(args) -> int>
auto wrap_callback(void* data, int argc, char* argv[]) {
return func(args(argv, argc));
}
int register_callback(std::string_view name, callback_t fun) {
return foo_register_callback(std::string(name).c_str(), fun);
}
// template <typename F>
// int register_callback2(std::string_view name, F fun) {
// return foo_register_callback(std::string(name).c_str(), wrap_callback<fun>);
// }
}
// Note that echo doesn't use the void* data provided in the callback
auto echo(foo::args args) -> int {
for (size_t k = 1; k < args.size(); k++) {
if (k > 1) {
std::cout << " ";
}
std::cout << args[k];
}
std::cout << "\n";
return 0;
}
auto main(int argc, char* argv[]) -> int {
foo::register_callback("echo", foo::wrap_callback<echo>);
// foo::register_callback2("echo", echo);
}
Закомментированные строки кода показывают, что я хотел бы сделать. Я хочу переместить foo::wrap_callback
в пределах foo::register_callback
, чтобы пользователь написал register_callback("echo", echo)
вместо register_callback("echo", wrap_callback<echo>)
.
В настоящее время это не работает. Сообщения об ошибках, которые я получаю, не особенно полезны и создают впечатление, будто я столкнулся с ошибкой компилятора, но она не срабатывает как в Clang 9, так и в GCC 10.
<source>: In instantiation of 'int foo::register_callback2(std::string_view, F) [with F = int (*)(std::span<char* const, 18446744073709551615>); std::string_view = std::basic_string_view<char>]':
<source>:38:41: required from here
<source>:21:37: error: no matches converting function 'wrap_callback' to type 'int (*)(void*, int, char**)'
21 | return foo_register_callback(std::string(name).c_str(), wrap_callback<fun>);
| ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:11:10: note: candidate is: 'template<int (* func)(foo::args)> auto foo::wrap_callback(void*, int, char**)'
11 | auto wrap_callback(void* data, int argc, char* argv[]) {
| ^~~~~~~~~~~~~
Должно ли это работать? Есть ли другие способы сделать то, что я хочу?
Вот ссылка на Compiler Explorer для примера.