【问题标题】:How do I convert a function wrapper in to templates?如何将函数包装器转换为模板?
【发布时间】:2012-07-18 19:00:22
【问题描述】:

我有几个非常相似的功能:

v8::Handle<v8::Value> jsAudioPlay(const v8::Arguments &args) {
    Audio *audio = static_cast<Audio*>(args.This()->GetPointerFromInternalField(0));
    if (audio != NULL) audio->play(get(args[0], 0));
    return args.This();
}

v8::Handle<v8::Value> jsAudioPause(const v8::Arguments &args) {
    Audio *audio = static_cast<Audio*>(args.This()->GetPointerFromInternalField(0));
    if (audio != NULL) audio->pause();
    return args.This();
}

v8::Handle<v8::Value> jsAudioLoop(const v8::Arguments &args) {
    Audio *audio = static_cast<Audio*>(args.This()->GetPointerFromInternalField(0));
    if (audio != NULL) audio->loop(get(args[0], -1));
    return args.This();
}

v8::Handle<v8::Value> jsAudioVolume(const v8::Arguments &args) {
    Audio *audio = static_cast<Audio*>(args.This()->GetPointerFromInternalField(0));
    if (audio != NULL) audio->volume(get(args[0], 1.0f));
    return args.This();
}

我已经阅读 C++ 模板几个小时了,我确信可以摆脱这些函数并用模板替换它们。我设想最终结果将是这样的:

typedef Handle<Value> (*InvocationCallback)(const Arguments& args);

template <class T> InvocationCallback FunctionWrapper ...;
template <class T> FunctionWrapper FunctionReal ...;
template <class T, class arg1> FunctionWrapper FunctionReal ...;
template <class T, class arg1, class arg2> FunctionWrapper FunctionReal ...;

我知道有人问过类似的问题,但我在上述模板中找不到模板示例。


2012 年 7 月 21 日更新

模板:

template <class T> v8::Handle<v8::Value> jsFunctionTemplate(const v8::Arguments &args) {
    T *t = static_cast<T*>(args.This()->GetPointerFromInternalField(0));
    if (t != NULL) t->volume(args[0]->NumberValue());
    return args.This();
}

用法:

audio->PrototypeTemplate()->Set("Volume", v8::FunctionTemplate::New(&jsFunctionTemplate<Audio>));

现在,如果我能弄清楚如何将&amp;Audio::volume 传递给模板,那我就成功了。


2012 年 7 月 24 日更新

请参阅我的回答,了解我是如何解决这个问题的。

【问题讨论】:

  • 相同的一般想法here,最终被称为wrap (someFunc, arg1, arg2, arg3)。我希望这至少是一个开始。
  • 您使用的是什么版本的编译器?具体来说,你能用C++11吗?
  • gcc (Gentoo 4.5.3-r2 p1.1, pie-0.4.7) 4.5.3 -- 如何确定是否可以使用 C++11?
  • @Caleb :您可以将here 列出的 C++11 功能的子集用于
  • 模板参数T的意义何在?您似乎只需要使用 Audio 作为模板参数来实例化它,那么为什么还要在该类型上对其进行参数化呢?你想要一个可以调用不同函数的函数模板,但总是为Audio,对吧?

标签: c++ templates


【解决方案1】:

欢迎来到 lambda 的魔力。

template<typename F> v8::Handle<v8::Value> jsAudio(const v8::Arguments &args, F&& f) {
    Audio *audio = static_cast<Audio*>(args.This()->GetPointerFromInternalField(0));
    if (audio != NULL) f(audio, args);
    return args.This();
}
int main() {
    jsAudio(..., [&](Audio* audio, const v8::Arguments &args) {
        audio->play(get(args[0], 0));
    });
}

例如。

【讨论】:

  • 虽然这绝对让我走上了正轨,但是否有可能让它更通用?我使用这些模板作为回调:audio-&gt;PrototypeTemplate()-&gt;Set("Play", v8::FunctionTemplate::New(&amp;jsAudioPlay)); 所以他们需要保留他们的InvocationCallback 类型...我希望代码看起来像这样:audio-&gt;PrototypeTemplate()-&gt;Set("Play", v8::FunctionTemplate::New(jsFunctionTemplate&lt;Audio, Audio::play&gt;)); 我可以弄清楚该怎么做可变数量的参数。
  • @CalebGray,定义“更通用”。该函数非常通用,它可以传递任何可调用对象,例如 lambda、bind(&amp;Audio::play, _1, bind(&amp;get, bind(&amp;Args::operator[], _2, 0), 0))bind(&amp;Audio::pause, _1)function&lt;void(Audio&amp;, const Arguments&amp;)&gt; 或合适的仿函数等。
  • 问题是,我需要将结果作为指向函数的指针传递:v8::FunctionTemplate::New(&amp;jsFunctionTemplate&lt;Audio&gt;),据我所知,这个答案改变了函数的 decltype,因此它破坏了我的能力将其用作回调。有关我当前的解决方案,请参阅我的答案。
【解决方案2】:

我的模板:

template <class T, class RT, RT(T::*f)()> v8::Handle<v8::Value> jsFunctionTemplate(const v8::Arguments &args) {
    T *t = static_cast<T*>(args.This()->GetPointerFromInternalField(0));
    if (t != NULL) (t->*f)();
    return args.This();
}
template <class T, class RT, class A0, RT(T::*f)(A0)> v8::Handle<v8::Value> jsFunctionTemplate(const v8::Arguments &args) {
    T *t = static_cast<T*>(args.This()->GetPointerFromInternalField(0));
    if (t != NULL) (t->*f)(jsConvert<A0>(args[0]));
    return args.This();
}
template <class T, class RT, class A0, class A1, RT(T::*f)(A0, A1)> v8::Handle<v8::Value> jsFunctionTemplate(const v8::Arguments &args) {
    T *t = static_cast<T*>(args.This()->GetPointerFromInternalField(0));
    if (t != NULL) (t->*f)(jsConvert<A0>(args[0]), jsConvert<A1>(args[1]));
    return args.This();
}

用法:

audio->PrototypeTemplate()->Set("Play", v8::FunctionTemplate::New(&jsFunctionTemplate<Audio, Audio*, int, &Audio::play>));
audio->PrototypeTemplate()->Set("Pause", v8::FunctionTemplate::New(&jsFunctionTemplate<Audio, Audio*, &Audio::pause>));
audio->PrototypeTemplate()->Set("Loop", v8::FunctionTemplate::New(&jsFunctionTemplate<Audio, Audio*, int, &Audio::loop>));
audio->PrototypeTemplate()->Set("Volume", v8::FunctionTemplate::New(&jsFunctionTemplate<Audio, Audio*, float, &Audio::volume>));

现在我需要弄清楚最后两个步骤:可变数量的参数,以及正确模板 jsConvert 以返回所需的类型 &lt;A0&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    相关资源
    最近更新 更多