C++ decltype行为背后的基本原理是什么?
正如我在C++11中所理解的那样,C++ decltype行为背后的基本原理是什么?,c++,c++11,c++14,decltype,type-deduction,C++,C++11,C++14,Decltype,Type Deduction,正如我在C++11中所理解的那样,decltype(expression)用于推导与给定表达式完全相同的类型。但当表达式本身放入括号中时,推断类型是对表达式类型的左值引用。例如: int x; decltype(x) y = x; 相当于int y=x但是 int x; decltype((x)) y = x; 相当于int&y=x 分别 decltype(auto) f1() { int x = 0; return x; // decltype(x) is int, so
decltype(expression)
用于推导与给定表达式完全相同的类型。但当表达式本身放入括号中时,推断类型是对表达式类型的左值引用。例如:
int x;
decltype(x) y = x;
相当于int y=x代码>但是
int x;
decltype((x)) y = x;
相当于int&y=x代码>
分别
decltype(auto) f1()
{
int x = 0;
return x; // decltype(x) is int, so f1 returns int
}
但是
标准委员会选择这种行为的理由是什么
后记:
现在我观察到,至少在gcc6.2实现的情况下,当括号中的表达式更复杂时,例如decltype((x+x))
推导的类型是T
,而不是T&
。这更令人困惑。我不知道这种行为是否标准。需要区分实体和表达式
考虑以下问题:
密西西比河有多长
这个问题有两个答案:
密西西比河有2320英里长
密西西比河有11个字母长
同样,当您询问x
的类型,并且x
是一个标识符时,不清楚您指的是用于声明该标识符的类型(即与名称x
关联的类型),还是仅提及该标识符的表达式类型。事实上,可以有两个不同的关键字(例如实体类型
和表达式类型
),而不是一个重载的decltype
。出于某种原因,委员会选择为这两种不同的用途重载decltype
。他们想要一种获得标识符声明类型的方法
他们还希望找到一种获取表达式类型的方法,包括关于它是否是临时表达式的信息
decltype(x)
给出标识符的声明类型x
。如果您传递的decltype
不是标识符,它将确定类型,然后为左值追加&
,为xvalues追加&
,为prvalues追加任何内容
从概念上讲,您可以将其视为变量类型和表达式类型之间的差异。但这并不是标准所描述的
他们可以用两个不同的关键词来表示这两件事。他们没有。来自decltype
提案的作者之一J.Jarvi:
已经有一段时间了,但我(想我)还记得:
区分这两种语义的两个单独的关键字
从未考虑过。(引入新关键字并非易事)
关于decltype((x))
的语义变化,在
核心工作组将(x)
视为一种表达,而不是
而不是标识符,它可能更“内部一致”
遵守语言规则
人们意识到,在某些情况下,这可能会令人困惑
但共识(也许不是每个人的偏好)是一致的
最终与本标准的先前定义保持一致
什么是标识符,什么是表达式
你链接到[这个问题的例子]的例子确实令人惊讶。当时,推导出一个
使用decltype(auto)
还不是语言的一部分,所以我不认为这个特殊的用法
任何人都注意到了这个案子
也许这会很有帮助,他们需要一些方法使decltype能够产生一个ref。所以他们只是滚动随机语法骰子来产生括号。@TartanLlama,decltype(auto)
出现了c++14
,而decltype
规范是这样的,因为c++11
,对我来说,这似乎不是原因。老实说,我觉得这是自然的方式decltype(identifier)
是标识符的类型。如果它是一个非ID表达式,则它是T值,如果它是一个LValk,因为C++是这样说的:“指定其他事物的LV值”,显然他们希望人们停止随机地对他们的<代码>返回< /Calp>表达式进行括号化。但是当我给出的不是一个标识符,比如“代码> DECKTYPE(X+1)< <代码>或<代码> DECKTYPE(1)。(x+1))
在这两种情况下,推导的类型都是int
,但不是int&
,也不是更具逻辑性的int&
(使用GCC 6.2和boost::type_索引库进行测试)。为什么?@bobeff因为x+1
是PR值?@bobeff注意decltype(x+1)
将始终与decltype((x+1))相同
无论x
的类型是什么,以及操作符+
如何重载。原因是x+1
是一个表达式,因此在其周围添加括号不会改变任何东西。@Columbo。可能是。From:prvalue不能是多态的:它标识的对象的动态类型始终是ty表达式的pe。decltype
不一定给出对象的动态类型,即使您说decltype(x)
。由x
引用的对象的实际类型(当x
是foo.bar
时)在编译时可能未知。在这种情况下,decltype
应该生成x
引用的成员的声明类型(换句话说,当我们在实体类型“class member”和“object”之间进行选择时,我们必须选择“class member”).这在规范中有点含糊不清,消歧依赖于语言和常识方面的先验知识/专业知识。
decltype(auto) f2()
{
int x = 0;
return (x); // decltype((x)) is int&, so f2 returns int&
}