C++ 函数指针返回值中对指针的强制转换引用

C++ 函数指针返回值中对指针的强制转换引用,c++,c++11,function-pointers,emscripten,C++,C++11,Function Pointers,Emscripten,EnScript生成从JavaScript调用C++函数的自动绑定。但是,如果函数返回一个引用,结果将按值传递给JavaScript。指针返回值通过引用传递。如果我有一个函数: MyType&MyClass::doStuff(intx,inty) 我可以这样做: 函数(“doStuff”,&MyClass::doStuff) 使其显示在JavaScript中。但我需要的是: 函数(“doStuff”,重新解释强制转换(&doStuff)) 使其返回指针。但是,为每个函数键入这样的内容很糟糕,因此

EnScript生成从JavaScript调用C++函数的自动绑定。但是,如果函数返回一个引用,结果将按值传递给JavaScript。指针返回值通过引用传递。如果我有一个函数:

MyType&MyClass::doStuff(intx,inty)

我可以这样做:

函数(“doStuff”,&MyClass::doStuff)

使其显示在JavaScript中。但我需要的是:

函数(“doStuff”,重新解释强制转换(&doStuff))

使其返回指针。但是,为每个函数键入这样的内容很糟糕,因此我需要一个神奇的宏来转换:

函数(“doStuff”,MAGIC(MyClass::doStuff))


在上面的版本中(对于使用任意数量的任何类型的参数的函数),使用强制转换或类似的方法。问题是:这在C++11中可能吗?

对函数指针(或成员函数指针)执行
重新解释转换是一个非常糟糕的主意

相反,编写一个适配器:

template<typename M, M m> struct make_wrapper_helper;
template<typename T, typename R, typename... A, R& (T::*m)(A...)>
struct make_wrapper_helper<R& (T::*)(A...), m> {
  R* (*operator()())(T&, A...) {
    return [](T& t, A ...a) -> R* { return &(t.*m)(static_cast<A>(a)...); };
  }
};
template<typename M, M m>
decltype(make_wrapper_helper<M, m>()()) make_wrapper() {
  return make_wrapper_helper<M, m>()();
}

function("doStuff", make_wrapper<decltype(&MyClass::doStuff), &MyClass::doStuff>())
模板结构make\u wrapper\u helper;
模板
结构make\u wrapper\u helper{
R*(*运算符())(T&,A…){
return[](T&T,A…A)->R*{return&(T.*m)(static_cast(A)…);};
}
};
模板
decltype(make_wrapper_helper())make_wrapper(){
返回make_wrapper_helper();
}
函数(“doStuff”,make_wrapper())

不幸的是,因为lambda必须是无捕获的,所以成员函数指针必须作为非类型模板参数传递,这意味着它不能被推导。您可以使用宏来解决此问题。

对函数指针(或成员函数指针)执行
重新解释强制转换是一个非常糟糕的主意

相反,编写一个适配器:

template<typename M, M m> struct make_wrapper_helper;
template<typename T, typename R, typename... A, R& (T::*m)(A...)>
struct make_wrapper_helper<R& (T::*)(A...), m> {
  R* (*operator()())(T&, A...) {
    return [](T& t, A ...a) -> R* { return &(t.*m)(static_cast<A>(a)...); };
  }
};
template<typename M, M m>
decltype(make_wrapper_helper<M, m>()()) make_wrapper() {
  return make_wrapper_helper<M, m>()();
}

function("doStuff", make_wrapper<decltype(&MyClass::doStuff), &MyClass::doStuff>())
模板结构make\u wrapper\u helper;
模板
结构make\u wrapper\u helper{
R*(*运算符())(T&,A…){
return[](T&T,A…A)->R*{return&(T.*m)(static_cast(A)…);};
}
};
模板
decltype(make_wrapper_helper())make_wrapper(){
返回make_wrapper_helper();
}
函数(“doStuff”,make_wrapper())

不幸的是,因为lambda必须是无捕获的,所以成员函数指针必须作为非类型模板参数传递,这意味着它不能被推导。您可以使用宏来解决此问题。

ecatmur完美地回答了这个问题,但我花了一些时间来理解代码的实际功能,因此这里有一个使用宏的注释版本:

// Helper type for PTR_RETURN() macro.
template<typename RetTypeRef, RetTypeRef method> struct ptrReturnHelper;
// Specialize the helper for a particular class, method and set of arguments.
template<
    typename Class,
    typename RetType,
    typename... ArgType,
    RetType &(Class::*method)(ArgType...)
> struct ptrReturnHelper<RetType &(Class::*)(ArgType...), method> {
    /* Function returning function pointer,
       called inside EMSCRIPTEN_BINDINGS block. */
    auto getWrapper()->auto(*)(Class &, ArgType...)->RetType * {
        /* PTR_RETURN() macro ultimately returns this lambda function which
           converts the original function pointer return value: */
        return [](Class &obj, ArgType ...arg) -> RetType * {
            return &(obj.*method)(static_cast<ArgType>(arg)...);
        };
    }
};

/* Convert a pointer to RetType &Class::method(ArgType...)
   into a pointer to    RetType *Class::method(ArgType...) */
#define PTR_RETURN(method) \
    (ptrReturnHelper<decltype(method),method>().getWrapper())
//PTR_RETURN()宏的帮助器类型。
模板结构ptrReturnHelper;
//专门化特定类、方法和参数集的帮助器。
模板<
typename类,
typename-RetType,
类型名。。。ArgType,
RetType&(类::*方法)(ArgType…)
>结构ptrReturnHelper{
/*函数返回函数指针,
在EMSCRIPTEN_绑定块内调用*/
auto getWrapper()->auto(*)(类和,ArgType…->RetType*{
/*PTR_RETURN()宏最终返回这个lambda函数
转换原始函数指针返回值:*/
return[](Class&obj,ArgType…arg)->RetType*{
返回和(obj.*方法)(静态_cast(arg)…);
};
}
};
/*将指针转换为RetType&Class::method(ArgType…)
指向RetType*Class::method(ArgType…)的指针*/
#定义PTR_返回(方法)\
(ptrReturnHelper().getWrapper())

ecatmur完美地回答了这个问题,但我花了一些时间才理解代码的实际功能,因此这里有一个使用宏的注释版本:

// Helper type for PTR_RETURN() macro.
template<typename RetTypeRef, RetTypeRef method> struct ptrReturnHelper;
// Specialize the helper for a particular class, method and set of arguments.
template<
    typename Class,
    typename RetType,
    typename... ArgType,
    RetType &(Class::*method)(ArgType...)
> struct ptrReturnHelper<RetType &(Class::*)(ArgType...), method> {
    /* Function returning function pointer,
       called inside EMSCRIPTEN_BINDINGS block. */
    auto getWrapper()->auto(*)(Class &, ArgType...)->RetType * {
        /* PTR_RETURN() macro ultimately returns this lambda function which
           converts the original function pointer return value: */
        return [](Class &obj, ArgType ...arg) -> RetType * {
            return &(obj.*method)(static_cast<ArgType>(arg)...);
        };
    }
};

/* Convert a pointer to RetType &Class::method(ArgType...)
   into a pointer to    RetType *Class::method(ArgType...) */
#define PTR_RETURN(method) \
    (ptrReturnHelper<decltype(method),method>().getWrapper())
//PTR_RETURN()宏的帮助器类型。
模板结构ptrReturnHelper;
//专门化特定类、方法和参数集的帮助器。
模板<
typename类,
typename-RetType,
类型名。。。ArgType,
RetType&(类::*方法)(ArgType…)
>结构ptrReturnHelper{
/*函数返回函数指针,
在EMSCRIPTEN_绑定块内调用*/
auto getWrapper()->auto(*)(类和,ArgType…->RetType*{
/*PTR_RETURN()宏最终返回这个lambda函数
转换原始函数指针返回值:*/
return[](Class&obj,ArgType…arg)->RetType*{
返回和(obj.*方法)(静态_cast(arg)…);
};
}
};
/*将指针转换为RetType&Class::method(ArgType…)
指向RetType*Class::method(ArgType…)的指针*/
#定义PTR_返回(方法)\
(ptrReturnHelper().getWrapper())

我不能把我的头绕在那
重新解释演员的身上
。它是如何工作的,或者甚至是如何工作的?它将MyType&MyClass::doStuff声明中的第一个&into*更改为。我非常确定使用
reinterpret\u cast
通过指向不同类型函数的指针调用函数是未定义的行为。这是特定于emscripten编译器的,因此如果它不可移植,则可以。假装一个引用是一个指针听起来并不是那么糟糕…我不能把我的头绕在那
重新解释\u cast
上。它是如何工作的,或者甚至是如何工作的?它将MyType&MyClass::doStuff声明中的第一个&into*更改为。我非常确定使用
reinterpret\u cast
通过指向不同类型函数的指针调用函数是未定义的行为。这是特定于emscripten编译器的,因此如果它不可移植,则可以。假装引用是指针听起来没那么糟糕…谢谢!我怀疑会有比演员更干净的方式,但不知道怎么做。这很有效,谢谢!我怀疑会有比演员更干净的方式,但不知道怎么做。这很有效。