首页 > 解决方案 > 如何将对象及其方法转换为仅使用方法参数即可调用的函数

问题描述

有一个功能

template<typename Class, typename MemberFuncPtr>
auto makeCallback( Class* a, MemberFuncPtr func )
{
    return [a, func]( auto&&... args )
    {
        return ( a->*func )( std::forward<decltype( args )>( args )... );
    };
}

它将对象指针及其成员方法转换为捕获它们的 lambda,以后只需使用方法的参数即可调用它们。它工作正常,除了一种情况,其中方法是虚拟的并在派生类中被覆盖,例如

#include <iostream>

struct Base
{
    virtual void g( int, int ) const
    {
        std::cout << "Base" << std::endl;
    }
};

struct Derived : Base
{
    virtual void g( int, int ) const override
    {
        std::cout << "Derived" << std::endl;
    }
};

template<typename Class, typename MemberFuncPtr>
auto makeCallback( Class* a, MemberFuncPtr func )
{
    return [a, func]( auto&&... args )
    {
        return ( a->*func )( std::forward<decltype( args )>( args )... );
    };
}

int main()
{
    Derived d;
    auto cb = makeCallback( &d, &Base::g );
    cb( 1, 2 );

    return 0;
}

makeCallback( &d, &Base::g )尽管程序打印“派生” ,但在这里。

有没有办法只修改makeCallback(包括对其签名的任何更改)以在程序输出中接收“Base”?

标签: c++lambdapolymorphismpointer-to-member

解决方案


你可以做一些改变:

template<typename Class, typename MemberFuncPtr>
auto makeCallback( Class* a, MemberFuncPtr func )
{
    return [a, func]( auto&&... args )
    {
        return std::invoke(func, a, std::forward<decltype( args )>( args )... );
    };
}

int main()
{
    Derived d;
    auto cb = makeCallback(&d, [](auto obj, auto&&... args){ obj->Base::g(args...); });
    cb( 1, 2 );
}

演示


推荐阅读