std::common_reference
Определено в заголовке <type_traits> | ||
|---|---|---|
template< class... T > struct common_reference; | (с C++20) |
Определяет общий тип ссылки для типов T..., то есть тип, к которому все типы в T... могут быть преобразованы или связаны. Если такой тип существует (как определяется по правилам ниже), член type называет этот тип. В противном случае члена type нет. Поведение не определено, если любой из типов в T... является неполным типом, кроме (возможно, с квалификаторами cv) void.
При задании типов ссылок common_reference пытается найти тип ссылки, к которому все заданные типы ссылок могут быть связаны, но может вернуть тип без ссылки, если не может найти такой тип ссылки.
- Если
sizeof...(T)равно нулю, членаtypeнет. - Если
sizeof...(T)равно единице (то есть,T...содержит только один типT0), членtypeназывает тот же тип, что иT0. - Если
sizeof...(T)равно двум (то есть,T...содержит два типаT1иT2):- Пусть тип
Sбудет простым общим типом ссылки дляT1иT2(как определено ниже). Тип-членtypeназываетSпри выполнении всех условий ниже:-
T1иT2оба являются типами ссылок -
Sявляется корректным
-
- Пусть тип
| (с C++23) |
- В противном случае, если
std::basic_common_reference<std::remove_cvref_t<T1>, std::remove_cvref_t<T2>, T1Q, T2Q>::typeсуществует, гдеTiQявляется унарным шаблоном алиаса, таким чтоTiQ<U>являетсяUс добавлением cv- и квалификаторов ссылокTi, то тип-членtypeназывает этот тип; -
- В противном случае, если
decltype(false? val<T1>() : val<T2>()), гдеvalявляется шаблонной функциейtemplate<class T> T val();, является допустимым типом, то тип-членtypeназывает этот тип; - В противном случае, если
std::common_type_t<T1, T2>является допустимым типом, то тип-членtypeназывает этот тип; - В противном случае, члена
typeнет.
- В противном случае, если
- Если
sizeof...(T)больше двух (то есть,T...состоит из типовT1, T2, R...), то еслиstd::common_reference_t<T1, T2>существует, членtypeобозначаетstd::common_reference_t<std::common_reference_t<T1, T2>, R...>если такой тип существует. Во всех других случаях членаtypeнет.
Простой общий тип ссылки для двух типов ссылок T1 и T2 определяется следующим образом:
- Если
T1являетсяcv1 X&иT2являетсяcv2 Y&(то есть оба являются типами ссылок на lvalue): их простой общий тип ссылки — этоdecltype(false? std::declval<cv12 X&>() : std::declval<cv12 Y&>()), где cv12 — это объединение cv1 и cv2, если этот тип существует и является типом ссылки; - Если
T1иT2являются типами ссылок на rvalue: если существует простой общий тип ссылки дляT1&иT2&(определяемый по предыдущему пункту), тогда пустьCобозначит соответствующий тип ссылки на rvalue для этого типа. Еслиstd::is_convertible_v<T1, C>иstd::is_convertible_v<T2, C>являются типами ссылок на rvalue, то простой общий тип ссылки дляT1иT2естьC; - В противном случае один из двух типов должен быть типом ссылки на lvalue
A&, а другой — типом ссылки на rvalueB&&(AиBмогут быть с квалификаторами cv). ПустьDобозначит простой общий тип ссылки дляA&иB const&, если он существует. ЕслиDсуществует иstd::is_convertible_v<B&&, D>являетсяtrue, то простым общим типом ссылки будетD; - В противном случае простого общего типа ссылки не существует.
См. Условный оператор для определения типа выражения false ? X : Y, подобных использованным выше.
Типы-члены
| Имя | Определение |
|---|---|
type | общий тип ссылки для всех T... |
Вспомогательные типы
template< class... T > using common_reference_t = typename std::common_reference<T...>::type; | ||
template< class T, class U, template<class> class TQual, template<class> class UQual >
struct basic_common_reference {};
|
Шаблон класса basic_common_reference является точкой кастомизации, которая позволяет пользователям влиять на результат common_reference для типов, определенных пользователем (обычно, псевдоссылки). Основной шаблон пустой.
Специализации
Программа может специализировать std::basic_common_reference<T, U, TQual, UQual> по первым двум параметрам T и U если std::is_same_v<T, std::decay_t<T>> и std::is_same_v<U, std::decay_t<U>> оба являются true и по крайней мере один из них зависит от типа, определенного программой.
Если такая специализация имеет член с именем type, он должен быть общедоступным и однозначным членом, обозначающим тип, в который могут быть преобразованы как TQual<T>, так и UQual<U>. Кроме того, std::basic_common_reference<T, U, TQual, UQual>::type и std::basic_common_reference<U, T, UQual, TQual>::type должны обозначать один и тот же тип.
Программа не может специализировать basic_common_reference по третьим или четвёртым параметрам, и не может специализировать common_reference само по себе. Программа, добавляющая специализации, нарушающие эти правила, имеет неопределённое поведение.
Стандартная библиотека предоставляет следующие специализации basic_common_reference:
|
(C++23) | определяет общий тип ссылки для двух пар (специализация шаблона класса) |
|
(C++23) | определяет общий тип ссылки для кортежа и типа, подобного кортежу (специализация шаблона класса) |
|
(C++23) | определяет общий тип ссылки для объекта типа `std::reference_wrapper` и обычного типа (специализация шаблона класса) |
Примечания
| Макрос проверки наличия функции | Значение | Стандарт | Функция |
|---|---|---|---|
__cpp_lib_common_reference | 202302L | (C++23) | Сделать std::common_reference_t std::reference_wrapper типом ссылки |
Примеры
#include <concepts>
#include <type_traits>
static_assert(
std::same_as<
int&,
std::common_reference_t<
std::add_lvalue_reference_t<int>,
std::add_lvalue_reference_t<int>&,
std::add_lvalue_reference_t<int>&&,
std::add_lvalue_reference_t<int>const,
std::add_lvalue_reference_t<int>const&
>
>
);
int main() {}См. также
|
(C++11) | определяет общий тип группы типов (шаблон класса) |
|
(C++20) | указывает, что два типа имеют общий тип ссылки (концепция) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/types/common_reference