В основном вы запрашиваете полностью динамически набранные и проверенные вызовы функций.
Чтобы иметь полностью динамические вызовы функций, вам, в основном, нужно выбросить систему вызова функций C ++.
Это плохая идея, но я скажу вам, как это сделать.
Динамически вызываемый объект выглядит примерно так:
using dynamic_function = std::function< std::any( std::vector<std::any> ) >
где использовать
struct nothing_t {};
когда мы хотим вернуть void
.
Затем вы пишете механизм, который берет объект и определенную подпись и оборачивает его.
template<class R, class...Args, class F>
struct dynamic_function_maker {
template<std::size_t...Is>
dynamic_function operator()(std::index_sequence<Is...>, F&& f)const {
return [f=std::forward<F>(f)](std::vector<std::any> args)->std::any {
if (sizeof...(Is) != args.size())
throw std::invalid_argument("Wrong number of arguments");
if constexpr( std::is_same< std::invoke_result_t<F const&, Args... >, void >{} )
{
f( std::any_cast<Args>(args[Is])... );
return nothing_t{};
}
else
{
return f( std::any_cast<Args>(args[Is])... );
}
};
}
dynamic_function operator()(F&& f)const {
return (*this)(std::make_index_sequence<sizeof...(Args)>{}, std::forward<F>(f));
}
};
template<class R, class...Args, class F>
dynamic_function make_dynamic_function(F f){
return dynamic_function_maker<R,Args...,F>{}(std::forward<F>(f));
}
затем вы захотите вывести сигнатуры указателей функций и тому подобное:
template<class R, class...Args>
dynamic_function make_dynamic_function(R(*f)(Args...)){
return dynamic_function_maker<R,Args...,F>{}(std::forward<F>(f));
}
template<class Tclass R, class...Args>
dynamic_function make_dynamic_function(T* t, R(T::*f)(Args...)){
return dynamic_function_maker<R,Args...,F>{}(
[t,f](auto&&...args)->decltype(auto){return (t->*f)(decltype(args)(args)...);}
);
}
затем, после исправления опечаток, приведенных выше, вы сможете решить свою исходную проблему.
Опять же, как человек, который действительно может написать и понять приведенный выше код, Я настоятельно советую вам не использовать его . Хрупкий и опасный.
Почти никогда нет веских причин хранить обратные вызовы в тех местах, где вы не знаете, с какими аргументами вы будете их вызывать.
Должен быть отдельный тип и экземпляр CCC
для каждого набора аргументов, с которым вы хотите вызвать его. 99/100 раз, когда люди задают этот вопрос, они задают неправильный вопрос.