# std::common_reference

From cppreference.com
< cpp‎ | types

Defined in header `<type_traits>` |  |
template< class... T > struct common_reference; |  | (since C++20)

Determines the common reference type of the types `T...`, that is, the type to which all the types in `T...` can be converted or bound. If such a type exists (as determined according to the rules below), the member `type` names that type. Otherwise, there is no member `type`. The behavior is undefined if any of the types in `T...` is an incomplete type other than (possibly cv-qualified) void.

When given reference types, `common_reference` attempts to find a reference type to which the supplied reference types can all be bound, but may return a non-reference type if it cannot find such a reference type.

- If sizeof...(T) is zero, there is no member `type`.
- If sizeof...(T) is one (i.e., `T...` contains only one type `T0`), the member `type` names the same type as T0.
- If sizeof...(T) is two (i.e., `T...` contains two types `T1` and `T2`):
  - Let type `S` be the simple common reference type of `T1` and `T2` (as defined below). The member type `type` names `S` if all of the conditions below are satisfied:
    - `T1` and `T2` are both reference types
    - `S` is well-formed

std::is_convertible_v<std::add_pointer_t<T1>, std::add_pointer_t<S>> and std::is_convertible_v<std::add_pointer_t<T2>, std::add_pointer_t<S>> are true; | (since C++23)

  - Otherwise, if std::basic_common_reference<std::remove_cvref_t<T1>, std::remove_cvref_t<T2>, T1Q, T2Q>::type exists, where `TiQ` is a unary alias template such that TiQ<U> is `U` with the addition of `Ti`'s cv- and reference qualifiers, then the member type `type` names that type;

- - Otherwise, if decltype(false? val<T1>() : val<T2>()), where `val` is a function template template<class T> T val();, is a valid type, then the member type `type` names that type;
  - Otherwise, if std::common_type_t<T1, T2> is a valid type, then the member type `type` names that type;
  - Otherwise, there is no member `type`.
- If sizeof...(T) is greater than two (i.e., `T...` consists of the types `T1, T2, R...`), then if std::common_reference_t<T1, T2> exists, the member `type` denotes std::common_reference_t<std::common_reference_t<T1, T2>, R...> if such a type exists. In all other cases, there is no member `type`.

The simple common reference type of two reference types `T1` and `T2` is defined as follows:

- If `T1` is `cv1 X&` and `T2` is `cv2 Y&` (i.e., both are lvalue reference types): their simple common reference type is decltype(false? std::declval<cv12 X&>() : std::declval<cv12 Y&>()), where cv12 is the union of cv1 and cv2, if that type exists and is a reference type;
- If `T1` and `T2` are both rvalue reference types: if the simple common reference type of `T1&` and `T2&` (determined according to the previous bullet) exists, then let `C` denote that type's corresponding rvalue reference type. If std::is_convertible_v<T1, C> and std::is_convertible_v<T2, C> are both true, then the simple common reference type of `T1` and `T2` is `C`;
- Otherwise, one of the two types must be an lvalue reference type `A&` and the other must be an rvalue reference type `B&&` (`A` and `B` might be cv-qualified). Let `D` denote the simple common reference type of A& and B const&, if any. If D exists and std::is_convertible_v<B&&, D> is true, then the simple common reference type is `D`;
- Otherwise, there's no simple common reference type.

See Conditional operator for the definition of the type of expression false ? X : Y like the ones used above.

### Member types

Name | Definition
`type` | the common reference type for all `T...`

### Helper types

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 {}; |  |

The class template `basic_common_reference` is a customization point that allows users to influence the result of `common_reference` for user-defined types (typically proxy references). The primary template is empty.

### Specializations

A program may specialize std::basic_common_reference<T, U, TQual, UQual> on the first two parameters `T` and `U` if std::is_same_v<T, std::decay_t<T>> and std::is_same_v<U, std::decay_t<U>> are both true and at least one of them depends on a program-defined type.

If such a specialization has a member named `type`, it must be a public and unambiguous member that names a type to which both TQual<T> and UQual<U> are convertible. Additionally, std::basic_common_reference<T, U, TQual, UQual>::type and std::basic_common_reference<U, T, UQual, TQual>::type must denote the same type.

A program may not specialize `basic_common_reference` on the third or fourth parameters, nor may it specialize `common_reference` itself. A program that adds specializations in violation of these rules has undefined behavior.

The standard library provides following specializations of `basic_common_reference`:

std::basic_common_reference<std::pair> (C++23) | determines the common reference type of two `pair`s (class template specialization)
std::basic_common_reference<tuple-like> (C++23) | determines the common reference type of a `tuple` and a `tuple-like` type (class template specialization)
std::basic_common_reference<std::reference_wrapper> (C++23) | determines the common reference type of `reference_wrapper` and non-`reference_wrapper` (class template specialization)

### Notes

Feature-test macro | Value | Std | Feature
--- | --- | --- | ---
`__cpp_lib_common_reference` | `202302L` | (C++23) | Make std::common_reference_t of std::reference_wrapper a reference type

### Examples

Run this code

    #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() {}

### See also

common_type (C++11) | determines the common type of a group of types (class template)
common_reference_with (C++20) | specifies that two types share a common reference type (concept)

Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/types/common_reference&oldid=170267"