无法从类型 x 转换为类型 x

Cannot Convert From type x to type x

本文关键字:类型 转换      更新时间:2023-10-16

我得到了一个简单的类,它只是包装了一个类方法的函数调用。编译(使用Visual Studio 2013(时,我收到错误消息:

错误 2 错误 C2664: 'Sleipnir::Core::D elegate::D elegate(const Sleipnir::Core::D elegate &(' : 无法将参数 2 从 void (__cdecl *((void *const ,int &&('

转换为 void (__cdecl *((void *const ,int &&(' d:\programmieren\delegate\delegate\delegate\delegate.h 29 1 Delegate

这并没有真正的帮助。

我的代码:

    template<typename T>
    class Delegate;
    template<typename R, typename... A>
    class Delegate<R(A...)>
    {
        using TFunc = R(*)(void* const, A&&...);
    private:
        Delegate(void* const obj, TFunc stub)
            : _objectPtr(obj),
            _stubPtr(stub){}
    public:
        Delegate(R(*const funcPtr)(A...))
            : Delegate(nullptr, functionStub<R(*)(A...)>)
        {
        }
    private:
        template <R(*funcPtr)(A...)>
        static R functionStub(void* const, A&&... args)
        {
            return funcPtr(::std::forward<A>(args)...);
        }
    private:
        void*   _objectPtr;
        TFunc   _stubPtr;
    };

有人知道为什么会发生这种情况,或者如何解决它?

我发现的第一个问题是您将functionStub引用为 functionStub<R(*)(A...)>这是错误的,因为functionStub采用函数指针,而不是类型。合乎逻辑的解决方法是将funcPtr的地址作为functionStub<funcPtr>传入,但这也会失败。我相信这是因为函数参数不是常量表达式,因此传入 funcPtr 地址的格式不正确,因为模板只能使用常量表达式和类型进行实例化。

所以我在评论中建议你应该通过将funcPtr的签名更改为以下内容来传递给functionStub的参数:

static R functionStub(R (*funcPtr)(A...), void* const, A... args);

随之而来的问题是函数类型与TFunc不同。您可以通过先std::bind() functionStub funcPtr来解决此问题:

: Delegate(nullptr, std::bind(&functionStub, funcPtr, placeholders::_1))

这也需要将TFunc更改为std::function

using TFunc = std::function<R (void* const, A...)>;

现在我们已经摆脱了错误,但绑定只为调用放置一个参数。 A...可以是任意数量的参数,因此我们必须使用一些机制来放置可变参数数。

可以使用 easy_bind() 方法,如此线程中所示。

: Delegate(nullptr, easy_bind(&functionStub, funcPtr))

最后,&functionStub不能通过easy_bind()的参数推断为std::function类型,所以你可以为此使用make_function()

template <class Callable>
std::function<Callable> make_function(Callable* callable)
{
    return { callable };
}
// ...
: Delegate(nullptr, easy_bind(make_function(&functionStub), funcPtr))

演示

由于

以下行而失败:

using TFunc = R(*)(void* const, A&&...);
委托的公共构造函数服从于私有构造函数

,私有构造函数需要一个指针,该函数采用 void* 后跟 int。您正在传递一个仅接受 int 的函数。

我怀疑您正在寻找一个可以处理自由函数和采用上下文参数(例如this指针(的函数的委托。

std::function会为您处理所有这些事情。你能用std::function<R(A&&...)>来写你的委托吗?如果是这样,则可以使用 std::bind 来存储成员函数回调的对象指针。

现在让它工作了,感谢0x499602D2

下面是我的委托类的代码:

    template <class Callable>
    std::function<Callable> make_function(Callable* callable)
    {
        return{ callable };
    }
    template<typename T>
    class Delegate;
    template<typename R, typename... A>
    class Delegate<R(A...)>
    {
        using TFunc = std::function<R(void* const, A...)>;
    private:
        Delegate(void* obj, TFunc stub)
            : _objectPtr(obj),
            _stubPtr(stub)
        {}
    public:
        Delegate(R(*funcPtr)(A...))
            : Delegate(nullptr, easy_bind(make_function(&functionStub), funcPtr))
        { }
        template <class C>
        Delegate(C* const objectPtr, R(C:: * const methodPtr)(A...))
            : Delegate(objectPtr, easy_bind(make_function(&methodStub<C>), methodPtr))
        { }
        template <class C>
        Delegate(C* const objectPtr, R(C:: * const methodPtr)(A...) const)
            : Delegate(objectPtr, easy_bind(make_function(&constMethodStub<C>), methodPtr))
        { }
    public:
        R operator()(A... args) const
        {
            return _stubPtr(_objectPtr, ::std::forward<A>(args)...);
        }
    private:
        static R functionStub(R(*funcPtr)(A...), void* const, A... args)
        {
            return funcPtr(std::forward<A>(args)...);
        }
        template <class C>
        static R methodStub(R(C::* const methodPtr)(A...), void* const objectPtr, A... args)
        {
            return (static_cast<C*>(objectPtr)->*methodPtr)(std::forward<A>(args)...);
        }
        template <class C>
        static R constMethodStub(R(C::* const methodPtr)(A...) const, void* const objectPtr, A... args)
        {
            return (static_cast<C*>(objectPtr)->*methodPtr)(std::forward<A>(args)...);
        }
    private:
        void*   _objectPtr;
        TFunc   _stubPtr;

以及我如何在主课中使用它:

    void test(int x)
{
    std::cout << "Test - print: " << x << std::endl;
}
struct Printer
{
    void print(int x){
        std::cout << "Printer - print: " << x << std::endl;
    }
    void print2(int x) const{
        std::cout << "Printer - print2: " << x << std::endl;
    }
};
int main(int argc, void* args)
{
    Printer printer;
    Delegate<void(int)> del(&test);
    Delegate<void(int)> del2(&printer, &Printer::print);
    Delegate<void(int)> del3(&printer, &Printer::print2);
    del(1);
    del2(1);
    del3(1);
}