Как я могу переместить эту специализацию шаблона в общую функцию? - PullRequest
0 голосов
/ 19 октября 2019

У меня есть несколько обратных вызовов, которые требуют, чтобы в подписи было 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 для примера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...