enqueue()
принимает T&&
, который просто ограничивает его этим типом, вызов конструктора не происходит в результате передачи аргумента, потому что он не является типом значения.
Когда вы вызываете enqueue()
однако вы создаете временный T
, который будет вызывать его конструктор копирования из const T& value
, который вы ему передаете.
Впоследствии временный становится параметром для enqueue()
, который, в свою очередь, , затем создает другое prvalue T
, на этот раз инициализированное вашим (теперь) параметром lvalue, приведенным к T&&
, который, если T
имеет конструктор перемещения, вызовет его.
В противном случае, если T
не имеет конструктора перемещения (и не имеет явно удаленного конструктора), он «откатится» к вызову конструктора копирования, если он присутствует.
Поскольку вы передаете временное значение move_value_somewhere()
ему нужно будет принять либо T&&
, const T&
, или T
- при условии, что тип T
имеет жизнеспособный конструктор, чтобы сделать все это возможным.