2016-07-23 60 views
5

有没有什么办法可以使用符合条件的成员函数std::mem_fnstd :: mem_fn带有ref_qualified成员函数

下面的代码编译失败:

class DeadPool { 
public: 
    void jump() & { 
    std::cout << "Did not jump\n"; 
    } 

    void jump() && { 
    std::cout << "Jumped from helicopter\n"; 
    } 
}; 

int main() { 
    DeadPool dp1; 
    //auto cobj = std::mem_fn(&DeadPool::jump); // Won't compile 
    //cobj(dp1); 
    //cobj(DeadPool()); 
    using Func = void (DeadPool::*)() &; // lvalue ref qualifier explicitly provided 
    Func fp = &DeadPool::jump; // This works, as expected 
    (std::move(dp1).*fp)(); 
    return 0; 
} 

错误消息:

mem_fn_ex.cc:18:15: error: no matching function for call to 'mem_fn'
auto cobj = std::mem_fn(&DeadPool::jump); // Won't compile ^~~~~~~~~~~ /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/functional:1233:1: note: candidate template ignored: couldn't infer template argument '_Rp' mem_fn(_Rp _Tp::* __pm)^mem_fn_ex.cc:23:18: error: pointer-to-member function type 'Func' (aka 'void (DeadPool::*)() &') can only be called on an lvalue (std::move(dp1).*fp)(); ~~~~~~~~~~~~~~^

编译器:在两个锵(3.4)和g ++(5.3)

以为可以使使用这样一个事实,即在std::_Mem_fn类实现中右值对象被调用,如下所示:

return (std::move(__object).*__pmf)(std::forward<_Args>(__args)...); 

这可能会很好地调用rvalue this特定的成员函数,但由于签名在编译时不同,因此它不能这样做。

回答

4

问题是,您正在将超载函数传递到函数模板中 - mem_fn()无法推导出哪个jump()需要。您将需要通过特定的一个具有投:

auto cobj = std::mem_fn(static_cast<void (DeadPool::*)() &>(&DeadPool::jump)); 
cobj(dp1);  // ok 
cobj(DeadPool()); // error 

然而,这是由于双方的冗长一个非常不令人满意的解决方案(这是输入了很多)和局限性(你有& - 和&& -qualified过重的原因,但你只能使用一个?)。最好在这里使用一个通用的lambda:

auto jump = [](auto&& pool){ std::forward<decltype(pool)>(pool).jump(); }; 
jump(dp1);   // ok: Did not jump 
jump(DeadPool()); // ok: Jumped from helicopter 
+0

这让我想到为什么'this'不是基于ref限定符而被重载。任何想法 ? – Arunmu

+0

@Arunmu这与这个问题有什么关系? – Barry

+0

那么,如果编译器以这种方式实现它,那么有问题的代码可能会起作用。 – Arunmu