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

Template argument deduction and expression rules

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

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

int b;
foo(std::move(b));

两个问题:

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

所以a+b显然returns一个A&。但是表达式的类型是 A。那是对的吗 ? declval(a+b)又是一头猛兽,returnsA&

  1. 所描述的程序是准确的。
  2. 引用已从表达式类型中删除。但是一个表达式得到另一个属性,value-category,它映射到函数调用表达式的那种引用[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] 中删除引用不会丢失引用带给类型的信息。此信息由 value-category.

表示