“在扣除自动之前使用变量”的解决方法

问题描述 投票:0回答:1

我正在创建包装函数,修改现有函数(目标)。目标在运行时确定为没有类型信息的指针 (

void*
)。基本方案是这样的:

bool wrap(void* f, void** t)
{
    *t = magic();  // target determined at runtime as void*
    return true;
}


// define new wrapping function and storage for target
int(*foo_target)(int);

int foo(int data)
{
    return foo_target(data) + 10;
}

auto res = wrap(reinterpret_cast<void*>(&foo), reinterpret_cast<void**>(&foo_target));

wrap
函数是一个占位符,负责完成所有繁重的工作。对于每个目标,我定义一个包装函数 (
foo
) 和一个变量来存储指向具有正确类型的目标函数的函数指针 (
foo_target
)。

这可行,但需要丑陋的类型转换,并且我必须保持

foo_target
foo
的签名同步。我想要的是这样的:

template <class F>
struct wrap
{
    F* target;

    wrap(F&& f)
    {
        target = reinterpret_cast<F*>(magic());
    }
};

static auto foo = wrap(
    [](int data) -> int
    {
        return foo.target(data) + 10;     // ERROR
        // return 10;                     // WORKS
    });
}

所需的单一类型转换隐藏在

wrap
函数中,并且目标函数的签名位于单个位置。当然,这是行不通的,因为
foo
不能像这样在 lambda 中使用。

如果我使用公共基类,我就可以使这个解决方案发挥作用。但是,在这种情况下,我需要在每个包装函数中进行类型转换,并且必须定义函数签名两次。

struct wrap_base
{
    void* target;
};

template <class F>
struct wrap : wrap_base
{
    wrap(F&& f)
    {
        target = magic();
    }
};


static wrap_base foo = wrap(
    [](int data) -> int
    {
        using func = int(int);
        return reinterpret_cast<func*>(foo.target)(data) + 10;
    });
c++ lambda c++17
1个回答
0
投票

即使使用

void*
,函数指针也无法可移植地转换为
reinterpret_cast
。来自 expr.reinterpret.cast:

有条件地支持将函数指针转换为对象指针类型,反之亦然。这种转换的含义是实现定义的,除了如果实现支持双向转换,则将一种类型的纯右值转换为另一种类型并返回(可能具有不同的 cv 限定)将产生原始指针值。

© www.soinside.com 2019 - 2024. All rights reserved.