Spec-Zone.ru › C++

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 является корректным
  • std::is_convertible_v<std::add_pointer_t<T1>, std::add_pointer_t<S>> и std::is_convertible_v<std::add_pointer_t<T2>, std::add_pointer_t<S>> являются true;
(с 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&, а другой — типом ссылки на rvalue B&& (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:

std::basic_common_reference<std::pair>
(C++23)
определяет общий тип ссылки для двух пар
(специализация шаблона класса)
std::basic_common_reference<tuple-like>
(C++23)
определяет общий тип ссылки для кортежа и типа, подобного кортежу
(специализация шаблона класса)
std::basic_common_reference<std::reference_wrapper>
(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() {}

См. также

common_type
(C++11)
определяет общий тип группы типов
(шаблон класса)
common_reference_with
(C++20)
указывает, что два типа имеют общий тип ссылки
(концепция)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/types/common_reference

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API