在转换T-s时完美转发非T参数 [英] Perfect-forward non-T arguments while converting T-s

查看:220
本文介绍了在转换T-s时完美转发非T参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(此问题来自此答案

我试图修改一个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 to Object{pyob}, but forward all other arguments through. How can I fix the function to perfect-forward all arguments apart from those of type PyObject*, 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); 
        }
    }
};

DEMO

这篇关于在转换T-s时完美转发非T参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆