Сохранение ссылки на функцию с переменными аргументами в элементе данных в C

#c #class #templates #variadic-templates #c 20

#c #класс #шаблоны #переменные-шаблоны #c 20

Вопрос:

Я хочу сохранить ссылку на функцию с переменным числом аргументов в элементе данных класса и вызвать ее позже следующим образом:

 auto my_action = new ExecuteAction("Add", add, 1, 2);
std::vector<ExecuteAction *> execute_actions;
execute_actions.push_back(my_action);
// ...
auto my_action_retrieved = execute_actions.at(0);
my_action_retrieved->execute();
  

Обратите внимание, что add() , например, определяется следующим образом:

 void add(int a, int b) {
    std::cout << a   b << std::endl;
}
  

Самое близкое решение, которое я мог получить до сих пор, заключается в следующем:

 template<typename Function, typename... Arguments>
class ExecuteAction {
    static_assert(!(std::is_rvalue_reference_v<Arguments> amp;amp; ...));

    std::string option_name;
    Function function;
    std::tuple<Arguments...> arguments;

public:
    template<typename ForwardFunction, typename... ForwardArguments,
            typename = std::enable_if_t<(std::is_convertible_v<ForwardArguments amp;amp;, Arguments> amp;amp; ...)>>
    explicit ExecuteAction(std::string amp;option_name,
                           ForwardFunction amp;amp;function,
                           ForwardArguments amp;amp;... arguments)
            : function(std::forward<ForwardFunction>(function)),
              arguments{std::forward<ForwardArguments>(arguments)...} {
        this->option_name = option_name;
    }

    void execute() {
        std::apply(function, arguments);
    }
};

template<typename Function, typename... Arguments>
auto make_execute_action(std::string option_name, Function amp;amp;function, Arguments amp;amp;... arguments) {
    return new ExecuteAction<std::decay_t<Function>, std::remove_cv_t<std::remove_reference_t<Arguments>>...>
            (option_name, std::forward<Function>(function), std::forward<Arguments>(arguments)...);
}
  

Этот код может быть успешно вызван следующим образом:

 auto add_action = make_execute_action("Add", [](int a, int b) {
    std::cout << a   b << std::endl;
}, 1, 2);
add_action->execute();
  

Однако это решение имеет следующие проблемы:

  • Функции должны передаваться с помощью лямбда-выражения, но я хочу передавать ссылки на функции (как в примере выше)
  • Использование универсального std::vector не представляется возможным, поскольку параметры шаблона должны быть определены конкретно

Существует ли реализация в C или до C 20 , которая удовлетворяет моим требованиям?

Комментарии:

1. «Есть ли реализация на C» ? C? это опечатка?

2. @idclev463035818: Нет, я думал о varags том, что теоретически можно было бы использовать

3. В C var_args тоже есть

4. std::function и std::bind ? Конечно, это требует, чтобы все функции имели одинаковую подпись.

5. @Someprogrammerdude: но я хочу, чтобы аргументы были полностью произвольными по типу и количеству для передачи в ссылку на функцию при выполнении вызова