簡體   English   中英

構造可變參數模板參數列表

[英]Construct variadic template argument list

說我有以下情況:

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_* (在某種容器中)獲取並存儲相應的變量,然后使用這些值來調用函數對象,該對象作為模板參數傳遞。

這應該可以幫助您入門。 我已經模擬了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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM