2017-09-06 1 views
2

Ich experimentierte mit Vorlagen und Weiterleitung. Ich habe einen einfachen experimentellen Code geschrieben, der mich überrascht hat. Ich möchte diesen Mechanismus besser verstehen, wahrscheinlich fehlt mir hier etwas Wissen und darum bitte ich um Hilfe. Könntest du mir bitte erklären, warum die beiden Aufrufe in dem unten stehenden Code nicht kompiliert werden (PLATZ 2 und 3)?Weiterleitung von Parametern von Vorlagen zu Funktionen verschiedener Typen

#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&&' 
} 

Ich verstehe nicht, warum der Fehler sagt etwas über int Umwandlung in int & &, wenn ich Wert b vom Typ int.

+0

Kommentieren Sie nicht den Code, nach dem Sie fragen. Die Syntaxhervorhebung erschwert das Lesen. – Barmar

+0

Ok, daran werde ich mich erinnern. – YotKay

Antwort

1

Das Problem besteht darin, dass Sie der Funktion explizite Vorlagenargumente zur Verfügung stellen. Weiterleitungsargumente funktionieren nicht, wenn Sie die Vorlagenargumente explizit für den Typ angeben, den Sie weiterleiten möchten (es sei denn, Sie wissen wirklich, was Sie tun).

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

Wenn Sie h1<int, decltype(h2ref)> schreiben, erhalten Sie eine Funktion wie folgt aus:

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

int&& eine andere Art von int und kann nicht auf einen L-Wert vom Typ int wie die gebunden werden b, die Sie übergeben; es kann nur auf rvalues ​​vom Typ int


gebunden, wenn Sie die Vorlage Argumente weglassen, es funktioniert einfach:

h1(b, h2ref); 

Dies wird eine Funktion instanziiert, die wie folgt aussieht:

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

Ah, richtig. Jetzt verstehe ich es. Danke vielmals! – YotKay

+1

"int && ist ein anderer Typ als int und kann nicht implizit von int erstellt werden" IMHO, das ist eine sehr zwielichtige Erklärung. 'int' ist ein Typ, und' int && 'kann an Ausdrücke dieses Typs binden, aber nur, wenn die Wertkategorie dieses Ausdrucks (anders als der Typ) rvalue ist. Das Problem tritt auf, weil ein 'int &&' nicht an einen Lvalue vom Typ 'int' binden kann. –

+0

@NirFriedman Warum ist es ein Problem, 'int',' int & 'und' int && 'als völlig unterschiedliche Typen mit Konvertierungsregeln zu sehen, die mit lvalue/rvalue-Regeln von C++ übereinstimmen? – Justin

Verwandte Themen