2016-07-23 12 views
5

std::mem_fnでref修飾メンバ関数を使用する方法はありますか?ref_qualifiedメンバ関数を持つstd :: mem_fn

以下のコードはコンパイルに失敗します。

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クラス実装では、以下のようにrvalueオブジェクトが呼び出されます。

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 

しかし、それが原因冗長性(つまり、タイプするLOTだ)と制限(あなたは&を持っているの両方に本当にあっけなく解決策だ - と&& -qualified何らかの理由でオーバーロードされますが、1つしか使用できませんか?)。

+0

これは、なぜこれが代わりにref修飾子に基づいてオーバーロードされないのかと考えています。何か案が ? – Arunmu

+0

@Arunmuこの質問とは何が関係していますか? – Barry

+0

コンパイラがそれをそのように実装したのであれば、問題のコードはおそらくうまくいきました。 – Arunmu

関連する問題