Désactivation de la déduction d'argument de modèle avec std::forward pour garantir un transfert correct
Considérez la définition de std::forward dans VS2010 :
<code class="cpp">template<class _Ty> inline _Ty&& forward(typename identity<_Ty>::type& _Arg) { // forward _Arg, given explicitly specified type parameter return ((_Ty&&)_Arg); }</code>
Le but du modèle d'identité est de désactiver la déduction des arguments du modèle. Pourquoi est-ce crucial dans ce scénario ?
La déduction d’argument de modèle conduirait à une déduction de type incorrecte. Si une référence rvalue à un objet de type X est transmise à une fonction modèle avec un type de paramètre T&, la déduction de l'argument du modèle déduirait T comme X, ce qui donnerait un type de paramètre X&. Cependant, pour un transfert parfait, le paramètre est une lvalue car il a un nom. Par conséquent, l'utilisation de la déduction d'argument de modèle dans std::forward ferait en sorte que le type de paramètre déduit soit une référence lvalue ou une référence const lvalue.
<code class="cpp">template<typename T> T&& forward_with_deduction(T&& obj) { return static_cast<T&&>(obj); }</code>
Considérez l'exemple suivant :
<code class="cpp">void test(int&){} void test(const int&){} void test(int&&){} template<typename T> void perfect_forwarder(T&& obj) { test(forward_with_deduction(obj)); } int main() { int x; const int& y(x); int&& z = std::move(x); test(forward_with_deduction(7)); // 7 is an int&&, correctly calls test(int&&) test(forward_with_deduction(z)); // z is treated as an int&, calls test(int&) // All the below call test(int&) or test(const int&) because in perfect_forwarder 'obj' is treated as // an int& or const int& (because it is named) so T in forward_with_deduction is deduced as int& // or const int&. The T&& in static_cast<T&&>(obj) then collapses to int& or const int& - which is not what // we want in the bottom two cases. perfect_forwarder(x); perfect_forwarder(y); perfect_forwarder(std::move(x)); perfect_forwarder(std::move(y)); }</code>
Dans cet exemple, le transfert parfait échoue car le paramètre dans perfect_forwarder est traité comme une référence lvalue ou const lvalue en raison de son nom. Cela conduit à une déduction de type incorrecte dans forward_with_deduction, entraînant une sémantique static_cast indésirable.
La désactivation de la déduction d'argument de modèle avec le modèle d'identité dans std::forward garantit que std::forward renvoie toujours une référence rvalue, ce qui est essentiel pour transmission parfaite et correcte des lvalues ainsi que des rvalues.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!