2017-09-14 2 views
3

Ich weiß, dass für die folgende Funktionrvalue Referenz oder Weiterleitungsreferenz?

template <typename T> 
void do_something(T&& arg); 

Die Funktionsparameter eine Weiterleitung Referenz. Aber ist es im folgenden Fall immer noch eine Weiterleitungsreferenz oder eine rvalue-Referenz?

template <typename T> 
class MyClass 
{ 
    void do_something(T&& arg); 
}; 

Ich denke, es ist immer noch eine Weiterleitung Verweis, aber ich bin mir nicht sicher. Außerdem möchte ich wissen, was getan werden kann, um eine rvalue-Referenz bzw. eine Weiterleitungsreferenz durchzusetzen, wenn das Ergebnis nicht das ist, was ich beabsichtigt habe.

Antwort

4

Es ist eine rvalue Referenz. Weiterleitungsreferenzen können nur in einem abgeleiteten Kontext angezeigt werden. Dies ist nur eine Elementfunktion, die einen R-Wert-Verweis auf den Vorlagenparameter Klasse akzeptiert.

Sie können nicht erzwingen, dass eine Weiterleitungsreferenz eine rvalue-Referenz ist, wenn Sie die Vorlagendargumentableitung für Funktionen beibehalten möchten. Wenn Sie nichts dagegen haben die Vorlage Argument der ganzen Ort spezifizieren, dann wird dies immer und immer nur einen rvalue Hinweis geben:

template<typename T> struct identity { using type = T; }; 

template <typename T> void func(typename identity<T>::type&&); 

Im Nachhinein gibt es tatsächlich eine Art und Weise Abzug zu erhalten, sondern Kraft nur rvalue refs akzeptiert werden (neben dem selbst dokumentieren eines in Simple 's Antwort). Sie können eine gelöschte lvalue Überlastung bieten:

template<typename T> 
void func(T&) = delete; 

template<typename T> 
void func(T&& s) 
{ 
    // ... 
} 

Die L-Wert-Überlastung ist speziellere wenn ein L-Wert übergeben. Und wegen gelöscht werden, wird eine etwas klare Fehlermeldung geben.

+1

Bedeutet decuced context, dass der Typ automatisch vom übergebenen Argument abgeleitet wird? Wenn ich Sie richtig verstehe, wird T nicht abgeleitet, weil es Teil der Klassensignatur ist. –

+0

@ MartinKalbfuß - Genau. Ein abgeleiteter Kontext ist, wenn Sie die freie Funktionsversion von do_something aufrufen. – StoryTeller

3

Der Weiter ich weiß, was getan werden kann rvalue Referenz

zu erzwingen Wenn Sie immer eine rvalue Referenz in einem abgeleiteten Kontext (und keine Weiterleitung Referenz) mögen, dann können Sie verwenden dies:

template< 
    typename T, 
    typename = std::enable_if_t<!std::is_lvalue_reference<T>::value> 
> 
using rval_ref = T&&; 

template<typename T> 
void foo(rval_ref<T> s) 
{ 
    // ... 
} 

foo kann nur mit einem R-Wert bezeichnet werden, und T wird keine Referenz sein (dh, wenn Sie foo mit std::string&& nennen, dann T wird sei std::string).

+0

Nicht schlecht. Der abhängige Typ wurde entfernt und SFINAE verwendet, um lvalue refs zu blockieren. +1 – StoryTeller

Verwandte Themen