2017-09-06 9 views
2

私はテンプレートと転送を試していました。私を驚かせた簡単な実験コードを書いた。私はこの仕組みをよりよく理解したいと思っています。おそらく私はここでいくつかの知識が不足しているので、私は助けを求めます。以下のコードの2つの呼び出しがコンパイルされない理由を説明してください(場所2と3)。テンプレートからさまざまな種類の関数へのパラメータの転送

#include <iostream> 
#include <memory> 
#include <utility> 
using namespace std; 

void h2rvalref(int&& i) { cout << "h2rvalref" << endl; } 
void h2ref(int& i) { cout << "h2ref" << endl; } 
void h2val(int i) { cout << "h2val" << endl; } 

template <class T, class X> 
void h1(T&& t, X x) { x(forward<T>(t)); } 

int main() 
{  
    // PLACE (1) 
    h1<int, decltype(h2rvalref)>(1, h2rvalref); 

    auto b = 1; 
    // PLACE (2) 
    // h1<int, decltype(h2ref)>(b, h2ref); // --> ERROR - no matching function..., cannot convert 'b' (type 'int') to type 'int&&' 

    // PLACE (3) 
    // h1<int, decltype(h2val)>(b, h2val); // --> ERROR - no matching function..., cannot convert 'b' (type 'int') to type 'int&&' 
} 

エラーが、私はint型の値bを持っているとき& &をintにint型の変換について何かを言う、なぜ私は理解していません。

+0

質問しているコードをコメントにしないでください。構文の強調表示により、読みにくくなります。 – Barmar

+0

これは覚えています。 – YotKay

答えて

1

問題は、明示的なテンプレート引数を関数に提供していることです。転送する型のテンプレート引数を明示的に指定すると、引数を転送することはできません(実際に何をしているのか分からない限り)。

template <class T, class X> 
void h1(T&& t, X x) { x(forward<T>(t)); } 

あなたがh1<int, decltype(h2ref)>を書くとき、あなたはこのように機能し得る:

void h1(int&& t, decltype(h2ref) x) { x(forward<int>(t)); } 

int&&intは異なるタイプであるとのようなタイプintの左辺値にバインドすることはできませんあなたが渡したb;あなたがテンプレート引数をオフのままにした場合、それが唯一のタイプint


の右辺値にバインドすることができ、それだけで動作します:

void h1(int& t, // int& && collapses to just int& 
     decltype(h2ref) x) { 
    x(forward<int&>(t)); 
} 

h1(b, h2ref); 

これは、このように見える機能をインスタンス化します

+0

ああ、そうです。今私はそれを理解する。どうもありがとう! – YotKay

+1

"int &&はint型とは異なる型で、int型から暗黙的に作成することはできません" IMHO、これは非常に日陰のある説明です。 'int'は型であり、' int &&'はその式の値カテゴリ(型とは異なる)がrvalueである場合に限り、その型の式にバインドできます。この問題は 'int &&'が 'int'型の左辺値にバインドできないために発生します。 –

+0

@NirFriedman 'int'、' int& '、' int &&'をC++のlvalue/rvalueの規則と一致する変換規則で完全に異なる型として見るのはなぜ問題なのですか? – Justin

関連する問題