2017-02-09 5 views
2

次のコードを考えてみてください:タイプはr値参照に推論されません。なぜそうではありませんか?

class CMyClass {}; 

template<class T> 
void func(T&& param) { 
     if (std::is_same<CMyClass, std::decay<T>::type>::value) 
      std::cout << "param is a CMyClass\n"; 
     if (std::is_same<T, CMyClass&>::value) 
      std::cout << "param is a CMyClass reference\n"; 
     else if (std::is_same<T, CMyClass&&>::value) 
      std::cout << "param is a CMyClass r-value reference\n"; 
     else if (std::is_same<T, const CMyClass&>::value) 
      std::cout << "param is a const CMyClass reference\n"; 
     else if (std::is_same<T, const CMyClass&&>::value) 
      std::cout << "param is a const CMyClass r-value reference\n"; 
     else if (std::is_same<T, const CMyClass>::value) 
      std::cout << "param is a constant CMyClass\n"; 
     else if (std::is_same<T, CMyClass>::value) 
      std::cout << "param is a CMyClass\n"; 
     else 
      std::cout << "param is not a CMyClass\n"; 
} 


CMyClass mc3; 
func(std::move(mc3)); 

この小さなプログラムからの出力はなぜMC3のタイプはr値の参照してくださいする

param is a CMyClass 
param is a CMyClass 

推測されていませんか?

+1

related/dupe:http://stackoverflow.com/questions/16373881/why-forwarding-reference-does-not-deduce-to-rvalue-reference-in-case-of-value – NathanOliver

+0

_「なぜmc3のタイプはr値参照になると推測されていませんか? "_それは1つではないからですか? –

+1

あなたのコードは、 'T'の型が何であるかをチェックしますが、' param'の型についての情報を表示します。 'param'の型は' T && 'ではなく' T'ではないので、あなたのプログラムは存在します。さて、 'T && 'を' CMyClass &&'とするために 'T'を代用するためにはどのような型が必要ですか?それで 'T 'とは何ですか? –

答えて

6

1がどこかに存在しなければならないにもかかわらず、私はこのために良いデュープを見つけることができません、申し訳ありません。用

控除のルール:コールfoo(expr)の文脈で

template <class T> 
void foo(T&&) 

は以下のとおりです。

  • exprはタイプUの左辺値である場合には、TU&とタイプとして推定されるT&&参照縮退のためにU&です。
  • exprタイプUの右辺値である場合、Tは、タイプT&&は、崩壊基準によるU&&あるUとして推定されます。あなたの例で

std::move(mc3)CMyClassの右辺値(具体的にはxValue)です。したがって、TCMyClassと推定されます。このチェック:Tは右辺値参照型と推測することはありませんよう

else if (std::is_same<T, CMyClass&&>::value) 
    std::cout << "param is a CMyClass r-value reference\n"; 

は本当であることはほとんどないでしょう。

func<CMyClass&&>(std::move(mc3)); 

具体的には次のように指定できます。代わりにあなたができることは、チェックです:

else if (std::is_same<T&&, CMyClass&&>::value) 
//     ~~~~ 

これは、引数がrvalueであるすべてのケースを処理します。確かに、あなたが単にいつもT&&をチェックすれば、それはあなたのすべての事件を適切に処理します。

+0

2番目の箇条書きでは、 "参照の崩壊のため"で終わります...しかし、何らかの崩壊が起こります(ただ一つの '&&'アプリケーションが関係しています)? –

3

なぜmc3のタイプがr値参照になると推測されていないのですか?

param右辺場合、Tfunc内部非基準であり、そしてT&&右辺値参照あります。

template <typename T> 
void func(T&& x) 
{ 
    std::is_same<T, something>{}; // (0) 
    std::is_same<T&&, something>{}; // (1) 
} 

(0)の場合:

  • Tあり、ここで、経験的T転送参照を取る関数の本体に何を意味するかを示す例です の値がの場合は、funcに渡されます。 (*)
  • T左辺値funcに渡されたときのためにT&です。 (1)の場合

右辺値funcに渡されるとき

  • T&&T&&あります。 左辺値funcに渡されたとき
  • T&&T&です。

あなたがstd::is_same<T&&, CMyClass>::valueを使用する場合は、T&T&&を取得する必要がありますどちらか。


(*):用語が不正確である "さ" ことに注意してください - func内部Tの様々な意味がtemplate argument deductionreference collapsingに依存します。要するに

x左辺値ある場合

  • T&

    • Tは次のように推定されます。それ以外の場合は

    • Tです。

  • 起因を崩壊参照に、T&&は:

      T&
    • 場合x左辺値あります。

    • T&&さもなければ - (>T&T& &&)。 T&& && - >T&&

+0

@EdgarRokyanこれは* prvalues *に当てはまりますが、* xvalues *には 'T &&'と推測されます。それにもかかわらず、私は言及するために私の答えを修正する*参照崩壊*が起こっている。 –

+2

何かが 'something ()'の文脈で何かを意味するものとして、 'T'は推測されますか?その行には控除はありません。 – Barry

+0

@Barry: 'something'を' std :: is_same'に変更しました。私が言いたいのは、 'func'の本体の中の' T'と 'T &&'の "意味"は、 'T'の推測の仕方や参照の崩壊の影響によって変わるということです。用語に問題があると思われる –

関連する問題