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>являются одновременноtrue, то простым общим ссылочным типом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 = 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) | определяет общий ссылочный тип двух pair (специализация шаблона класса) |
|
(C++23) | определяет общий ссылочный тип tuple и типа tuple-like (специализация шаблона класса) |
|
(C++23) | определяет общий ссылочный тип reference_wrapper и типа, не являющегося 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/cpp/types/common_reference