【问题标题】:C++20 - Call function declared as auto in templateC++20 - 在模板中调用声明为 auto 的函数
【发布时间】:2020-06-11 10:02:41
【问题描述】:

我正在用 C++ 构建一个 nodejs 插件,我正在尝试制作一个从 C++ 到节点的函数导出器。更确切地说,我正在尝试构建一个类似的功能:

std::string func(std::string param)
{
  return param;
}

void func_wrapper(const v8::FunctionCallbackInfo<v8::Value>& args)
{
    Isolate* isolate = args.GetIsolate();

    std::string str(*v8::String::Utf8Value(isolate, args[0]));
    auto ret = func(str).c_str();

    args.GetReturnValue().Set(String::NewFromUtf8(
        isolate, ret, NewStringType::kNormal).ToLocalChecked()); 
}

void Initialize(v8::Local<v8::Object> exports) 
{
  NODE_SET_METHOD(exports, "func", func_wrapper);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)

我试图让导出更多函数变得更容易,而无需手动创建包装器,如下所示:

template<auto Func>
void Export(const v8::Local<v8::Object>& exports, std::string name)
{
    auto wrapper = [](const v8::FunctionCallbackInfo<v8::Value>& args) {
        Isolate* isolate = args.GetIsolate();
        unsigned int lg = args.Length();

        auto ret = Func(args[0], args[1], ...) //how to?
    };
    NODE_SET_METHOD(exports, name.c_str(), wrapper);
}

std::string func(std::string param)
{
  return param;
}

void Initialize(v8::Local<v8::Object> exports) 
{
  Export<func>(exports, "func");
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)

但我不知道如何在我的导出函数中调用 Func。有什么方法可以一个一个地给函数一个参数?

【问题讨论】:

    标签: c++ node.js c++20


    【解决方案1】:

    包括:

    #include <functional>
    #include <utility>
    #include <type_traits>
    #include <concepts>
    #include <string>
    

    转换函数:

    decltype(auto) Convert(v8::Isolate* isolate, const v8::Local<v8::Value>& value,
                           std::type_identity<std::string>)
    {
        return *v8::String::Utf8Value(isolate, value);
    }
    
    template <std::integral T>
    decltype(auto) Convert(v8::Isolate* isolate, const v8::Local<v8::Value>& value,
                           std::type_identity<T>)
    {
        return v8::Integer::Cast(*value)->Value();
    }
    

    调用委托:

    template <typename R, typename... Args>
    auto Call(v8::Isolate* isolate, std::function<R(Args...)> f,
              const v8::FunctionCallbackInfo<v8::Value>& args)
    {
        static_assert(sizeof...(Args) <= v8::FunctionCallbackInfo<v8::Value>::kArgsLength);
        return [&] <std::size_t... Is> (std::index_sequence<Is...>) {
            return f(Convert(isolate, args[Is],
                             std::type_identity<std::remove_cvref_t<Args>>{})...);
        }(std::index_sequence_for<Args...>{});
    }
    

    导出函数:

    template <auto Func>
    void Export(const v8::Local<v8::Object>& exports, const std::string& name)
    {
        auto wrapper = [](const v8::FunctionCallbackInfo<v8::Value>& args) {
            v8::Isolate* isolate = args.GetIsolate();
            unsigned int lg = args.Length();
            auto ret = Call(isolate, std::function{ Func }, args);
        };
        NODE_SET_METHOD(exports, name.c_str(), wrapper);
    }
    

    【讨论】:

    • term 不计算为带 1 个参数的函数(第 11 行)pastebin.com/vAqt3FGf
    • @MihaiPreda 现在?所有参数是否总是std::string
    • 不,有完全相同的错误。不,参数并不总是 std::string,但类型的数量有限(我认为是 string、int 和 double),所以让它适用于其中一个就足够了。
    • 我稍微编辑了代码(从第一个答案开始),所以现在该函数将 args[i] 的类型作为参数。此代码编译:pastebin.com/gRyEXmH6(见第 25 行)
    • 成功了,谢谢你的帮助。它现在适用于字符串和双打,如果有人感兴趣,这就是我实现它的方式:pastebin.com/gRkPTTtC
    猜你喜欢
    • 1970-01-01
    • 2021-12-20
    • 2018-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多