c++ - 模板参数推导和表达式规则

标签 c++ templates language-lawyer c++20

我有一个关于这个 one 的后续问题: 符号 PA 引用 temp.deduct.call 部分 如果我正确理解模板参数推导,下面的代码会发生以下情况:

template<typename T>
void foo(const T& a);

int b;
foo(std::move(b));
  • 首先编译器推导出两种类型PA 分别用于参数声明和模板实参。我们正在推断声明是引用 const T&(但不是转发引用)
  • 的情况
  • 对于 A:std::move(b) 具有类型 int&& [xvalue] -> 调整为 A := 整数 ( [7.2.2#1] )
  • 对于 P:const T& -> 移除 const 和引用 ([ 12.9.2.1#3 ]) -> P:= T<
  • 模式匹配 AP -> 结果 T:= int

两个问题:

  1. 所描述的程序准确吗?
  2. std::move(b) 是一个表达式,我一直认为它的类型是 int&& (因为 std::move 返回一个int&&),但是 ( [7.2.2#1] ) 说明了一些不同的东西,这意味着在进行任何分析之前删除所有引用,因此当谈论表达式的类型时,永远不会涉及任何引用:
struct A{ A& operator+(const A&);}
A a, b;
auto c = a + b;

所以a+b显然返回了一个A&。但表达式的类型是 A。那是对的吗 ? declval(a+b) 是另一个怪兽,返回 A&

最佳答案

  1. 所描述的程序是准确的。
  2. 引用已从表达式类型中删除。但是表达式获得另一个属性,值类别,它映射到函数调用表达式的引用类型 [expr.call]/14 :

    A function call is an lvalue if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise.

这几乎可以用那些推理规则来表示:

function return type             function call expression [type,value-category]
     T&                  =>        [ T , lvalue ]
     T&&                 =>        [ T , xvalue ]
     T                   =>        [ T , prvalue ]

decltype 做反向映射,[dcl.type.decltype]/1 :

For an expression e, the type denoted by decltype(e) is defined as follows:

  • [...]
  • otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;

  • otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;

  • otherwise, decltype(e) is the type of e.

因此,引用带给类型的信息不会因删除 [expr.type] 中的引用而丢失。此信息由值类别表示。

关于c++ - 模板参数推导和表达式规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56627124/

相关文章:

c++ - 为什么 C++ 智能指针实现将引用计数器与指针一起保存在堆上?

c++ - 虚拟继承实际上是如何工作的?

c++ - 自定义 C++ 类上的错误

c - C中的声明与定义

html - 表格行可以没有单元格吗?

c++ - 如何获取 C++ 类成员 vector 的大小?

c++ - 错误 C2955 : use of class template requires template argument list

c++ - 公开模板类型的模板参数

visual-studio - VS2013 和 Azure - 部署模板验证失败,尽管我既没有编辑模板也没有编辑项目属性

c++ - 取消引用 null 并不总是 UB?