Выведенные операторы преобразования возвращаемого значения немного странные. Но основная идея заключается в том, что он действует как параметр функции, чтобы выбрать, какой из них используется.
И при выборе между T&&
и T&
на T&
победы в правилах разрешения перегрузки. Это разрешить:
template<class T>
void f( T&& ) { std::cout << "rvalue"; }
template<class T>
void f( T& ) { std::cout << "lvalue"; }
работать. T&&
может соответствовать lvalue, но когда доступны как lvalue, так и универсальные эталонные перегрузки, lvalue предпочтительнее.
Правильный набор операторов преобразования, вероятно:
template <typename T>
operator T&&() &&;
template <typename T>
operator T &() const; // maybe &
или даже
template <typename T>
operator T() &&;
template <typename T>
operator T &() const; // maybe &
чтобы предотвратить неудачное продление жизни от укуса.
3 Типы, используемые для определения порядка, зависят от контекста, в котором выполняется частичное упорядочение:
[СНиП]
(3.2) В контексте вызова функции преобразования используются типы возврата шаблонов функций преобразования.
Что в конечном итоге зависит от «более специализированных» правил при выборе перегрузок:
(9.1) если тип из шаблона аргумента был ссылкой lvalue, а тип из шаблона параметра не был, тип параметра не считается, по крайней мере, таким же специализированным, как тип аргумента; в противном случае,
Таким образом, operator T&&
по крайней мере, не так специализирован, как operator T&
, в то время как ни одно из государств-правил operator T&
не является, по крайней мере operator T&&
, столь же специализированным, как и operator T&
более специализированным, чем operator T&&
.
Более специализированные шаблоны выигрывают при разрешении перегрузки меньше, при прочих равных условиях.