模板参数推导和表达式规则
Template argument deduction and expression rules
关于这个 我有一个后续问题:
符号 P
和 A
指的是 temp.deduct.call 部分
如果我正确理解模板参数推导,下面的代码会发生以下情况:
template<typename T>
void foo(const T& a);
int b;
foo(std::move(b));
- 首先,编译器为参数声明和模板实参分别推导出两种类型
P
和A
。我们正在推断声明是引用 const T&
(但不是转发引用) 的情况
- 对于
A
:std::move(b)
具有类型 int&&
[xvalue] -> 调整为 A:= int
([7.2.2#1])
- 对于
P
:const T&
-> 删除常量和引用 ([12.9.2.1#3]) -> P:= T
- 模式匹配
A
与 P
-> 结果 T:= int
.
两个问题:
- 描述的程序准确吗?
std::move(b)
是一个表达式,我一直以为它的类型是int&&
(因为std::move
returns一个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&
。
- 所描述的程序是准确的。
引用已从表达式类型中删除。但是一个表达式得到另一个属性,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.
表示
关于这个 P
和 A
指的是 temp.deduct.call 部分
如果我正确理解模板参数推导,下面的代码会发生以下情况:
template<typename T>
void foo(const T& a);
int b;
foo(std::move(b));
- 首先,编译器为参数声明和模板实参分别推导出两种类型
P
和A
。我们正在推断声明是引用const T&
(但不是转发引用) 的情况
- 对于
A
:std::move(b)
具有类型int&&
[xvalue] -> 调整为A:= int
([7.2.2#1]) - 对于
P
:const T&
-> 删除常量和引用 ([12.9.2.1#3]) ->P:= T
- 模式匹配
A
与P
-> 结果T:= int
.
两个问题:
- 描述的程序准确吗?
std::move(b)
是一个表达式,我一直以为它的类型是int&&
(因为std::move
returns一个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&
。
- 所描述的程序是准确的。
引用已从表达式类型中删除。但是一个表达式得到另一个属性,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.
表示