2016-11-11 12 views
0

普遍的な参照を使用すると、誰かが次のコードタイプ控除

template< typename T > 
void check() 
{ 
    std::cout << "unknow type" << std::endl; 
} 

template<> 
void check<int>() 
{ 
    std::cout << "int" << std::endl; 
} 

template<> 
void check<int&>() 
{ 
    std::cout << "int&" << std::endl; 
} 

template<> 
void check<int&&>() 
{ 
    std::cout << "int&&" << std::endl; 
} 

template< typename T > 
void bar(T&& a) 
{ 
    check<T>(); 
} 

int main() 
{ 
    bar(0); 

    int a = 0; 
    bar(a); 
} 

の出力は

int 
int& 

なく

int&& 
int& 

である理由私は私の視点から理解するのに役立つことができますがr値参照がr値参照として残っており、l値参照がlval参照として残っている方が直感的ですしかし、l値参照のみがl値参照として残り、r値が非参照値となるように見える。 これの背後にあるモチベーション/アイデアは何ですか?即ちT専門bar<int>(int&&)を呼び出しbar(0);

+5

'check 'を使っていますが、 'check ';ではありません。どうして明示的に省略したときに' && 'がそこにあると思いますか? – ildjarn

+0

私は 'bar(0)'が 'bar (0)'と同じであると予想しました。 'bar(0)'の上のコードを 'bar (0)'に置き換えると、出力は実際には 'int && \ n int&'になります。 –

+3

'bar 'のタイプは 'void(T &&)'で、 'bar 'のタイプは' void(T && &&) 'です(参照の崩壊前)。 – Oktalist

答えて

4

intとして推定するのでcheck<T>()check<int>()です。パラメータタイプはT&&で、int&&ですが、これはパラメータのタイプであり、タイプはTではありません。

これは、転送していない参照と完全に一致しています。あなたが定義した場合:

template<typename T> void baz(T&); 

を、あなたがタイプintの左辺値でそれを呼び出してTintとして推定される、あなたの例で使用するようにフォワーディング参照に関する特別なのではないint&

唯一のことは、ことはT&&のためであります型は左辺値の参照として導き出すことができます。Rと呼びます。この場合、パラメータタイプはR&&で、Rと同じadd_rvalue_reference_t<R>と同じです。ですから、Tすなわち専門bar<int&>(int&)を呼び出すコールbar(a)int&

と推定されるため、明示的なテンプレート引数リストとbar<int&&>(0)を呼び出すときに引数控除がなく、パラメータの型T&&があるので、そうTは、int&&で置換されていますadd_rvalue_reference_t<int&&>はちょうどint&&です。

関連する問題