std::add_lvalue_reference, std::add_rvalue_reference
Материал из cppreference.com
<tbody>
</tbody>
| Определено в заголовочном файле <type_traits>
|
||
template< class T > struct add_lvalue_reference; |
(1) | (начиная с C++11) |
template< class T > struct add_rvalue_reference; |
(2) | (начиная с C++11) |
Создаёт левостороннюю или правостороннюю ссылку на тип T.
1) Если
T является функциональным типом, который не имеет cv- или ref-квалификатора, или объектным типом, предоставляет typedef элемент type, который равен T&. Если T является ссылкой rvalue на некоторый тип U, то type является U&. Иначе type равно T.2) Если
T является функциональным типом, который не имеет cv- или ref-квалификатора, или объектным типом, предоставляет typedef элемент type, который равен T&&, иначе type равно T.Поведение программы, добавляющей специализации для любых шаблонов, описанных на этой странице не определено.
Типы-элементы
| Имя | Определение |
type
|
ссылка на T, или T, если ссылку создать нельзя
|
Вспомогательные типы
<tbody> </tbody> template< class T > using add_lvalue_reference_t = typename add_lvalue_reference<T>::type; |
(начиная с C++14) | |
template< class T > using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; |
(начиная с C++14) | |
Примечание
Эти преобразования типов учитывают правила очистки ссылки:
std::add_lvalue_reference<T&>::typeравноT&std::add_lvalue_reference<T&&>::typeравноT&std::add_rvalue_reference<T&>::typeравноT&std::add_rvalue_reference<T&&>::typeравноT&&
Основное отличие от прямого использования T& заключается в том, что std::add_lvalue_reference<void>::type равно void, а void& приводит к ошибке компиляции.
Возможная реализация
namespace detail {
template <class T>
// или используйте std::type_identity (начиная с C++20)
struct type_identity { using type = T; };
template <class T> // Обратите внимание, что `cv void&` это ошибка подстановки
auto try_add_lvalue_reference(int) -> type_identity<T&>;
template <class T> // Обрабатывает T = cv void случай
auto try_add_lvalue_reference(...) -> type_identity<T>;
template <class T>
auto try_add_rvalue_reference(int) -> type_identity<T&&>;
template <class T>
auto try_add_rvalue_reference(...) -> type_identity<T>;
} // namespace detail
template <class T>
struct add_lvalue_reference
: decltype(detail::try_add_lvalue_reference<T>(0)) {};
template <class T>
struct add_rvalue_reference
: decltype(detail::try_add_rvalue_reference<T>(0)) {};
|
Пример
Запустить этот код
#include <type_traits>
int main()
{
using non_ref = int;
using l_ref = typename std::add_lvalue_reference_t<non_ref>;
using r_ref = typename std::add_rvalue_reference_t<non_ref>;
using void_ref = std::add_lvalue_reference_t<void>;
static_assert
( std::is_lvalue_reference_v<non_ref> == false
&& std::is_lvalue_reference_v<l_ref> == true
&& std::is_rvalue_reference_v<r_ref> == true
&& std::is_reference_v<void_ref> == false
);
}
Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
| Номер | Применён | Поведение в стандарте | Корректное поведение |
|---|---|---|---|
| LWG 2101 | c++11 | Эти свойства преобразования были необходимы для создания ссылок на cv/ref квалифицированные функциональные типы. |
Сами создают cv/ref квалифицированные функциональные типы. |
Смотрите также
(C++11) |
проверяет, является ли тип либо левосторонней ссылкой, либо правосторонней ссылкой (шаблон класса) |
(C++11) |
удаляет ссылку из данного типа (шаблон класса) |
(C++20) |
объединяет std::remove_cv и std::remove_reference (шаблон класса) |