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

См. также

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/cpp/types/common_reference

Spec-Zone.ru

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