Да, вы можете использовать свертывание ссылок, чтобы уменьшить объем написанной функции.
Например, ваша вставка функции может использовать ссылку rvalue + непосредственный контекст для использования свертывания ссылок, что приводит к пересылке ссылки:
template<typename U>
inline constexpr void insert(U &&v) { // v is a forwarding reference
if (!_root) {
// we use std::forward to keep rvalue-ness
// of the named object when v is an rvalue, but not when it's a lvalue
_root = std::make_unique<binary_search_tree_node>(std::forward<U>(v));
++_size;
} else {
insert(_root, std::forward<U>(v));
}
}
Даже если параметр использует ссылку rvalue, lvalue будет работать здесь из-за свертывания ссылки. Если U
выводит до int&
, то параметр имеет вид int& &&
, который сворачивается до int&
. Напротив, если передается значение r, оно выводит int
как U
, поэтому параметр равен int &&
.
Этот шаблон называется ссылкой для пересылки.
Когда вы Можно видеть, что такой код имеет это свойство только в том случае, если для параметра переадресации существует дедукция аргумента шаблона.
Имейте в виду, что если сделать его шаблоном, он будет принимать больше типов, чем предполагалось, если не ограничен правильно.
Вы также можете использовать копию и переместить ее, чтобы избежать дублирования кода:
inline constexpr void insert(const T &v) {
T copy = v;
insert(std::move(copy)); // calls the rvalue overload
}