2017-05-03 15 views
5

私は、以下の(壊れた)のコードに示すように、そのパラメータのoperator()を呼び出す必要があります機能foo書きたい:テンプレートパラメータの定数を転送するには、転送参照を使用する必要がありますか?

template <typename T> void foo(const T& x){ 
    x(); 
} 

struct MyFunctor{ 
    int data; 
    void operator()(){ 
     /* stuff that might modify the data */ 
    } 
}; 

int main() 
{ 
    foo(MyFunctor{}); 
} 

を明らかにコードが動作しない、operator()が非constあるために、しかし、 foo()のパラメータはconstである必要があります。

テンプレート関数として、foo()constと非constファンクタの両方で動作し、その引数のconst -nessうるさいすべきではありません。

私は次のようにconstを除去することにより、foo()を変更する場合:あなたはそう、非const左辺値参照に右辺値参照を変換することはできませんので、それはまた、動作しません...

template <typename T> void foo(T& x) { /* ... */ } 

foo(MyFunctor{})を呼び出すことはできません。

転送リファレンスにfoo()を変更するには、すべての問題を解決します

template <typename T> void foo(T&& x) { /* ... */ } 

をしかし、これは「正しい」方法は何ですか?転送参照をstd::forward()とだけ使用しないでください(つまり、パラメータを別の関数に転送する以外には触れないでください)。

+2

[C++ 11-Scott Meyersのユニバーサルリファレンス](https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers)をお読みください。 'T && x'の使い方を詳しく説明しています。 – VTT

+0

これは完璧ですIMO –

+0

私は6桁の評判を持つ人々に私の質問に答えることを光栄に思っています! – Bernard

答えて

3

はい、転送参照が正しい方法であり、それはあなたを落ち着かせた場合、あなたは確かにパラメータを転送することができます。

template <typename T> void foo(T&& x){ 
    std::forward<T>(x)(); 
} 

は今でもREF-資格呼び出し演算子で動作します。

+1

Ref-qualifiedコールオペレータは、あなたが今日私に教えてくれた新しいものです。 – Bernard

0

はい、これは転送参照の目的全体です。

パラメータは、あなたがやっている正確に何である別の関数

に転送別に触れてはいけません。

関連する問題