0

我有以下无法编译的代码,尤其是在通过 std::forward 转发之后

struct TestParent
{
    template< typename Fn >
    bool test( Fn&& fn )
    {
        //.. do something
        //.. check some condition
        bool someCondition = true;
        if ( someCondition )

        {
            //this call works!
            return fn();
        }

        return testAtNextLevel( std::forward< Fn >( fn ) );
    }

    template < typename Fn >
    bool testAtNextLevel( Fn&& fn )
    {
        if ( (this->*fn() )
        {
             return true;
        }

         //... test some more
         return true;
     }
}

struct TestChild: public TestParent
{
     bool thisTestOk();
     bool testAll();
}

bool TestChild::thisTestOk()
{
     return true;
}

bool testAll()
{
    auto myFunc = std::bind( &TestChild::thisTestOk, this );
    return test( myFunc );
}

编译时我收到此错误消息:

error: no match for 'operator->*' (operand types are 'TestParent*' and 'std::_Bind<std::_Mem_fn<bool (TestChild::*)()>(TestChild*)>')
 if ( (this->*fn)() )

任何人都知道为什么在通过 std::forward 后,该函数无法被调用?在基类中,在调用'testAtNextLevel'之前,如果满足某些条件,我们可以调用传入的函数,而不是在它被转发到另一个模板函数之后?

4

1 回答 1

1

使用所有这些模板和auto声明,很容易忘记您正在处理的数据类型。让我们从代码的底部开始:

auto myFunc = std::bind( &TestChild::thisTestOk, this );

是什么myFunc?虽然官方未指定返回类型,std::bind但指定了它的用途(例如,参见cppreference.com)。将此返回值作为函数调用等效于thisTestOk()将其唯一参数绑定到this.

也就是说,隐藏的指向TestChild参数的指针(存在于 的所有TestChild非静态成员函数中)已被 替换this,这具有将成员函数转换为非成员函数的效果。现在让我们看看如何调用这个包装器非成员函数。

test()中,此包装器通过 调用return fn()。它作为函数调用,并按预期工作。

testAtNextLevel()中,此包装器通过 调用this->*fn()。此包装器非成员函数作为指向成员函数的指针调用,这是一个错误。为了使它在语法上工作,调用应该是简单的fn(),就像它在test(). 如果您真的想覆盖绑定对象并this用作 的隐藏参数fn(),则需要将不同的东西作为参数传递给testAtNextLevel(),可能是指向成员的指针(并且它必须是指向成员的指针TestParent,不是指向成员的指针TestChild)。

于 2018-11-07T22:58:40.707 回答