2016-07-23 78 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