Вот код в VS2015:Почему ссылочный аргумент rvalue предпочитает ссылку const lvalue на параметр ссылки 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;
}
В случае 3, тип rref
является ссылка Rvalue, и его значение категория lvalue
, и называет push_back(const Elem &)
.
В случае 4, в соответствии с действующим Современной C++ Пункт 23, реализация std::move
что-то вроде
// C++ 14
template<typename T>
decltype(auto) move(T&& param)
{
using ReturnType = remove_reference_t<T>&&;
return static_cast<ReturnType>(param);
}
Тип std::move(e4)
является Elem &&
, и его значение категория prvalue
, вызывает push_back(Elem &&)
.
Так lvalue
из T&&
матчей const T &
и prvalue
из T&&
матчей T&&
, что же тип и категория значения выражения на самом деле при разрешении перегрузки между T
, const T &
и T &&
?
Извините, что не описал свою проблему четко. Так как многие ссылки говорят, что если категория значений аргумента равна prvalue
, будет вызвана функция с T&&
; значение категории lvalue
, будет вызвана функция с const T &
.
Могу ли я просто сказать, что тип аргумента используется для разрешения перегрузки, а категория значений проверяется для привязки ссылок, когда тип параметра является ссылкой?
Как только ваша переменная имеет имя, это lvalue –
http://stackoverflow.com/a/18766736/390913 – perreal