Построить список аргументов вариационного шаблона

Скажем, у меня есть следующий сценарий:

namespace detail
{
using duk_c_function_t = std::function<duk_ret_t(duk_context*)>;

template<typename T_Return(typename ... T_Params), std::function<T_Return(T_Params)>
duk_ret_t duk_function_proxy(duk_context* ctx)
{
const int n = sizeof...(T_Params); //real number of arguments passed.
duk_idx_t num_arguments = duk_get_top(ctx); //Number of arguments from javascript
int x = duk_require_int(ctx, 0); //Get integer -> parameter no 1
const char* c = duk_require_string(ctx, 1); //Get string -> parameter no 2
}
}
template<typename T_Return(typename ... T_Params)>
duk_c_function_t duk_function(std::function<T_Return(T_Params ...) function_item)
{
return duk_c_function_t(detail::duk_function_proxy<function_item>);
}

куда duk_function возвращает функцию подписи duk_ret_t function(duk_context* ctx) { ... }, Теперь я знаю, как вызвать объект функции в duk_function_proxy с различными шаблонами и тому подобное. Но есть одна проблема для меня: интерпретатор javascript, который я использую, требует, чтобы для каждой c-функции, которую я хочу представить, мне нужно было запрашивать параметры из стека, как показано в duk_function_proxy, Однако, учитывая это, я не знаю, как вызывать объект функции — я могу хранить запрошенные параметры только в каком-то контейнере, и, таким образом, я не могу вызвать объект функции с данной сигнатурой. Есть ли способ сохранить мои запрашиваемые параметры в каком-то контейнере, а затем распаковать и передать его объекту функции в качестве параметров? Я запрашиваю обязательные параметры на основе списка шаблонов переменных, как показано в прототипе.

Я хочу перебрать T_Params, получить и сохранить соответствующие переменные, используя duk_require_* (в каком-то виде контейнера), а затем используйте эти значения для вызова объекта функции, который передается в качестве аргумента шаблона.

1

Решение

это должно начать вас. Я смоделировал интерфейс DUK, так как он не установлен на моей машине, но вы поймете:

#include <iostream>
#include <string>
#include <functional>
#include <utility>

struct duk_context;

const char* duk_require_string(duk_context*, int i)
{
static constexpr const char * strings[] = {
"i like",
"hairy",
"ducks"};
return strings[i];
}

int duk_require_int(duk_context*, int i)
{
return i * 6;
}

template<class Type> auto get_arg(duk_context* ctx, int i) -> Type;

template<> auto get_arg<std::string>(duk_context* ctx, int i) -> std::string
{
return duk_require_string(ctx, i);
}

template<> auto get_arg<int>(duk_context* ctx, int i) -> int
{
return duk_require_int(ctx, i);
}

template<class...Args, size_t...Is>
void get_args_impl(duk_context* context, const std::function<void(Args...)>& f, std::index_sequence<Is...>)
{
using tuple_type = std::tuple<Args...>;
f(get_arg<std::tuple_element_t<Is, tuple_type>>(context, Is)...);
}

template<class...Args>
void get_args(duk_context* context, const std::function<void(Args...)>& f)
{
get_args_impl<Args...>(context, f, std::index_sequence_for<Args...>());
}

void foo(std::string a, int b, std::string c)
{
std::cout << a << " " << b << " " << c << std::endl;
}

int main()
{
duk_context* ctx = nullptr;

get_args(ctx, std::function<void(std::string, int, std::string)>(&foo));

return 0;
}

ожидаемый результат:

i like 6 ducks
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector