命名空间
变体
操作

std::common_reference

来自 cppreference.com
< cpp‎ | types
 
 
元编程库
类型特征
类型类别
(C++11)
(C++14)  
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
类型属性
(C++11)
(C++11)
(C++14)
(C++11)
(C++11)(直到 C++20*)
(C++11)(在 C++20 中已弃用)
(C++11)
类型特征常量
元函数
(C++17)
支持的操作
关系和属性查询
类型修改
(C++11)(C++11)(C++11)
类型转换
(C++11)(在 C++23 中已弃用)
(C++11)(在 C++23 中已弃用)
(C++11)
(C++11)
(C++17)

common_reference
(C++20)
(C++11)(直到 C++20*)(C++17)
编译时有理数运算
编译时整数序列
 
在头文件 <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... 包含两个类型 T1T2
    • 假设类型 ST1T2简单公共引用类型(定义如下)。如果以下所有条件都满足,则成员类型 type 将命名 S
      • T1T2 都是引用类型
      • S 是格式良好的
(自 C++23 起)
  • 否则,如果 std::basic_common_reference<std::remove_cvref_t<T1>, std::remove_cvref_t<T2>, T1Q, T2Q>::type 存在,其中 TiQ 是一个一元别名模板,使得 TiQ<U> 是添加了 Ti 的 cv 和引用限定符的 U,则成员类型 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

两个引用类型 T1T2简单公共引用类型定义如下

  • 如果 T1cv1 X&T2cv2 Y&(即,两者都是左值引用类型):它们的简单公共引用类型是 decltype(false? std::declval<cv12 X&>() : std::declval<cv12 Y&>()),其中 cv12cv1cv2 的并集,如果该类型存在并且是引用类型;
  • 如果T1T2 都是右值引用类型:如果T1&T2& 的简单公共引用类型(根据前一个项目符号确定)存在,则用C 表示该类型的相应右值引用类型。如果 std::is_convertible_v<T1, C>std::is_convertible_v<T2, C> 都是 true,则T1T2 的简单公共引用类型为C
  • 否则,两种类型中的一种必须是左值引用类型A&,另一种必须是右值引用类型B&&AB 可能是 cv 限定的)。设D 表示 A&B const& 的简单公共引用类型(如果有)。如果 D 存在且 std::is_convertible_v<B&&, D>true,则简单公共引用类型为D
  • 否则,不存在简单公共引用类型。

有关表达式类型 false ? X : Y 的定义,请参见 条件运算符,如上面使用的那些。

内容

[编辑] 成员类型

名称 定义
类型 所有 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 的结果。主要模板为空。

[编辑] 特化

程序可以对前两个参数 TU 特化 std::basic_common_reference<T, U, TQual, UQual>,如果 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>::typestd::basic_common_reference<U, T, UQual, TQual>::type 必须表示相同的类型。

程序不能对第三个或第四个参数特化 basic_common_reference,也不能特化 common_reference 本身。违反这些规则添加特化的程序具有未定义的行为。

标准库提供了以下 basic_common_reference 的特化

确定两个 pair 的公共引用类型
(类模板特化) [编辑]
确定 tupletuple-like 类型的公共引用类型
(类模板特化) [编辑]
确定 reference_wrapper 和非 reference_wrapper 的公共引用类型
(类模板特化) [编辑]

[编辑] 注释

特性测试 Std 特性
__cpp_lib_common_reference 202302L (C++23) 使 std::common_reference_tstd::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() {}

[编辑] 参见

确定一组类型的公共类型
(类模板) [编辑]
指定两种类型共享一个公共引用类型
(概念) [编辑]