在转换T-s时完美转发非T参数 [英] Perfect-forward non-T arguments while converting T-s
问题描述
(此问题来自此答案)
我试图修改一个trampoline函数,目前只是通过可变数量的参数。
I am trying to adapt a trampoline function that is currently just passing through a variable number of arguments.
我想让它转换任何参数 PyObject * pyob
到 Object {pyob}
,但转发所有其他参数。
I would like to have it convert any argument PyObject* pyob
to Object{pyob}
, but forward all other arguments through.
因此(void * self,int,PyObject *,float)
- > (int,Object,float) / code>
So (void* self, int, PyObject*, float)
-> (int, Object, float)
在该示例中,第一个 self
参数被删除。这总是发生。在剩余的参数中,其中一个是PyObject *类型,因此需要转换为Object。
In that example, the first self
argument is stripped away. This always happens. Out of the remaining arguments, one of them is of type PyObject*, and hence requires conversion to Object.
这里是函数:
template <typename T, T t>
struct trap;
template <typename R, typename... Args, R(Base::*t)(Args...)>
struct trap<R(Base::*)(Args...), t>
{
static R
call(void* s, Args... args)
{
std::cout << "trap:" << typeid(t).name() << std::endl;
try
{
return (get_base(s)->*t)(std::forward<Args>(args)...);
}
catch (...)
{
std::cout << "CAUGHT" << std::endl;
return std::is_integral<R>::value ? static_cast<R>(-42) : static_cast<R>(-3.14);
}
}
};
它似乎不是转发参数。我认为它正在制作每个参数的副本。我试过:
It appears not to be forwarding arguments. I think it is making a copy of each argument. I've tried:
call(void* s, Args&&... args)
但是这只会产生编译错误。
But that just generates compiler errors.
完整的测试用例这里
我如何修复该函数以完全转发除了类型PyObject *之外的所有参数,它应该转换为什么?
How can I fix the function to perfect-forward all arguments apart from those of type PyObject*, which it should convert?
推荐答案
$ b $
您不能完全按照向前的参数,它不是一个模板,或者通过指向一个函数的指针来调用,就像你所做的那样。 完美转发涉及模板参数扣除,在通过指针调用函数时不会发生该指针 - 该指针指向具体实例化<
You can't perfectly-forward arguments of a function which is not a template, or which is invoked through a pointer to a function, like you do. Perfect-forwarding involves a template argument deduction, which doesn't take place when you invoke a function through a pointer - that pointer points to a concrete instantiation of a function template.
std :: forward< Args>(args)
可以使用 move-constructor 从 call
的那些参数复制初始化目标函数的参数, / em>(或者通过硬编码的右值引用),或者让它们被右值引用绑定 - 你不需要任何更多的那些实例,你可以自由移动它们,保存至少一个复制操作。 (它可以简单到 static_cast< Args&&>(args)...
,因为它只是一个参考折叠)。
The std::forward<Args>(args)
expression is there to possibly utilize a move-constructor to copy-initialize the parameters of the target function from those arguments of call
that are passed by value (or by a hard-coded rvalue reference), or let them be bound by an rvalue reference - you won't need any more those instances, you are free to move-from them, saving at least one copy operation. (It could be as simple as static_cast<Args&&>(args)...
, because it's just a reference collapsing).
我想让它转换任何参数
PyObject * pyob
到Object {pyob}
,但转发所有其他参数。我如何修复该函数以完全转发除了PyObject *
类型的所有参数,它应该转换?
I would like to have it convert any argument
PyObject* pyob
toObject{pyob}
, but forward all other arguments through. How can I fix the function to perfect-forward all arguments apart from those of typePyObject*
, which it should convert?
#include <utility>
template <typename T, typename U>
T&& forward_convert(U&& u)
{
return std::forward<T>(std::forward<U>(u));
}
template <typename T>
Object forward_convert(PyObject* a)
{
return Object{a};
}
// ...
return (get_base(s)->*t)(forward_convert<Args>(args)...);
要替换调用
函数的签名时,使用 PyObject *
转发或转换参数,应该执行以下操作:
To replace any occurrence of Object
with PyObject*
while creating the signature of call
function, and only then conditionally forward or convert the arguments, you should do what follows:
template <typename T>
struct replace { using type = T; };
template <>
struct replace<Object> { using type = PyObject*; };
// you may probably want some more cv-ref specializations:
//template <>
//struct replace<Object&> { using type = PyObject*; };
template <typename T, T t>
struct trap;
template <typename R, typename... Args, R(Base::*t)(Args...)>
struct trap<R(Base::*)(Args...), t>
{
static R
call(void* s, typename replace<Args>::type... args)
{
try
{
return (get_base(s)->*t)(forward_convert<typename replace<Args>::type>(args)...);
}
catch (...)
{
return std::is_integral<R>::value ? static_cast<R>(-42) : static_cast<R>(-3.14);
}
}
};
这篇关于在转换T-s时完美转发非T参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!