命名空间
变体
操作

std::common_reference

来自 cppreference.cn
< cpp‎ | types
 
 
元编程库
类型特征
类型类别
(C++11)
(C++11)(DR*)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11) 
(C++11)
(C++11)
类型属性
(C++11)
(C++11)
(C++14)
(C++11)(在 C++26 中弃用)
(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++20*)(C++17)

common_reference
(C++20)
(C++11)
(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>U 加上 Ti 的 cv 和引用限定符,则成员类型 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 类型的定义(如上面使用的那些),请参见条件运算符

目录

[编辑] 成员类型

名称 定义
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::is_same_v<T, std::decay_t<T>>std::is_same_v<U, std::decay_t<U>> 都为 true,并且至少其中一个依赖于程序定义的类型,则程序可以特化前两个参数 TU 上的 std::basic_common_reference<T, U, TQual, UQual>

如果这样的特化具有名为 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() {}

[编辑] 参见

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