模板参数推导和表达规则

时间:2019-06-17 08:02:59

标签: 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&(而不是转发引用)的情况
  • 对于Astd::move(b)的类型为int&& [xvalue]->,其类型已调整为A:= int[7.2.2#1]
  • 对于Pconst T&->删除const和引用([12.9.2.1#3])-> P:= T
  • 针对A的模式匹配P->结果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 个答案:

答案 0 :(得分:4)

  1. 所描述的过程是准确的。
  2. 该引用已从表达式类型中删除。但是,表达式具有另一个属性 value-category ,该属性映射到函数调用表达式[expr.call]/14的引用类型:

      

    如果结果类型是左值引用类型或对函数类型的右值引用,则函数调用为左值;如果结果类型是对对象类型的右值引用,则为xvalue;否则为prvalue。

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

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

decltype执行反向映射,[dcl.type.decltype]/1

  

对于表达式e,由decltype(e)表示的类型定义如下:

     
      
  • [...]
  •   
  • 否则,如果e为x值,则decltype(e)为T &&,其中T为e的类型;

  •   
  • 否则,如果e为左值,则decltype(e)为T&,其中T为e的类型;

  •   
  • 否则,decltype(e)是e的类型。

  •   

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