std :: forward转发功能

时间:2018-11-07 20:23:00

标签: c++ templates forward-reference

我有以下代码无法编译,特别是在通过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”之前,如果满足某些条件,我们可以只调用传入的函数,而不能在将其转发到另一个模板函数之后调用?

1 个答案:

答案 0 :(得分: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()调用。这个包装器 non-member 函数被调用为指向成员函数的指针,这是一个错误。为了使它在语法上起作用,应该像在fn()中那样简单地调用test()。如果您确实想覆盖绑定的对象并使用this作为fn()的隐藏参数,则需要传递不同的参数作为testAtNextLevel()的参数,可能是指向成员的指针(并且它必须是指向TestParent成员的指针,而不是指向TestChild成员的指针)。