Voici un code à VS2015:Pourquoi l'argument de référence rvalue préfère-t-il la référence const lvalue au paramètre de référence rvalue?
class Elem
{
public:
Elem(int i) : a(i) {}
Elem(Elem && other) = default;
Elem(const Elem & other) = default;
private:
int a;
};
int main()
{
std::vector<Elem> vv;
// case 0
vv.push_back(Elem{ 0 }); // call push_back(Elem &&);
// case 1
Elem e1{ 1 };
vv.push_back(e1); // call push_back(const Elem &);
// case 2
Elem e2{ 2 };
auto & lref = e2;
vv.push_back(lref); // call push_back(const Elem &);
// case 3
Elem e3{ 3 };
auto && rref = std::move(e3);
vv.push_back(rref); // call push_back(const Elem &);
// case 4
Elem e4{ 4 };
vv.push_back(std::move(e4)); // call push_back(Elem &&);
return 0;
}
Dans le cas 3, le type de rref
est référence rvalue et sa catégorie de valeur est lvalue
et demande push_back(const Elem &)
.
Dans le cas 4, Selon moderne et efficace C++ Point 23, une implémentation de std::move
est quelque chose comme
// C++ 14
template<typename T>
decltype(auto) move(T&& param)
{
using ReturnType = remove_reference_t<T>&&;
return static_cast<ReturnType>(param);
}
Le type de std::move(e4)
est Elem &&
et sa catégorie de valeur est prvalue
, appelle push_back(Elem &&)
.
Ainsi, un lvalue
de T&&
correspond const T &
, et un prvalue
de T&&
matchs T&&
, qu'est-ce que le type et la catégorie de valeur d'une expression font réellement pendant la résolution de surcharge entre T
, const T &
et T &&
?
Désolé de ne pas avoir décrit clairement mon problème. Comme tant de liens ont dit que, si la catégorie de valeur d'un argument est prvalue
, la fonction avec T&&
sera appelée; la catégorie de valeur est lvalue
, la fonction avec const T &
sera appelée. Puis-je simplement dire que le type de l'argument est utilisé pour la résolution de surcharge, alors que la catégorie de valeur est vérifiée pour la liaison de référence lorsque le type du paramètre est une référence?
Dès que votre variable a un nom, c'est une valeur –
http://stackoverflow.com/a/18766736/390913 – perreal