std:: common_reference

From cppreference.com
Metaprogramming library
Type traits
Type categories
Type properties
(C++11)
(C++11)
(C++14)
(C++11) (deprecated in C++26)
(C++11) ( until C++20* )
(C++11) (deprecated in C++20)
(C++11)
Type trait constants
Metafunctions
(C++17)
Supported operations
Relationships and property queries
Type modifications
Type transformations
(C++11) (deprecated in C++23)
(C++11) (deprecated in C++23)
(C++11)
(C++11)
(C++17)

common_reference
(C++20)
(C++11) ( until C++20* ) (C++17)
Compile-time rational arithmetic
Compile-time integer sequences
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
(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 :

determines the common reference type of two pair s
(class template specialization)
determines the common reference type of a tuple and a tuple-like type
(class template specialization)
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

#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

determines the common type of a group of types
(class template)
specifies that two types share a common reference type
(concept)