[英]What's the type of the function call expression?
This is a language lawyer question. 这是一个语言律师问题。 Clause 5p5 in C++11 reads: C ++ 11中的第5p5条规定:
If an expression initially has the type “reference to T” (8.3.2, 8.5.3), the type is adjusted to T prior to any further analysis. 如果表达式最初具有“对T的引用”类型(8.3.2,8.5.3),则在进行任何进一步分析之前将类型调整为T. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression. 表达式指定由引用表示的对象或函数,表达式是左值或x值,具体取决于表达式。
On the other hand, §5.2.2p3 states: 另一方面,§5.2.2p3规定:
If the postfix-expression designates a destructor (12.4), the type of the function call expression is void; 如果postfix-expression指定析构函数(12.4),则函数调用表达式的类型为void; otherwise, the type of the function call expression is the return type of the statically chosen function (ie, ignoring the virtual keyword), even if the type of the function actually called is different. 否则,函数调用表达式的类型是静态选择函数的返回类型(即,忽略虚拟关键字),即使实际调用的函数的类型不同。 This type shall be an object type, a reference type or the type void. 此类型应为对象类型,引用类型或类型void。
Consider this piece of code: 考虑一下这段代码:
int& f();
f(); // What is the type of this expression?
This was corrected post publication of the standard, in DR 1261 . 在DR 1261中标准发布后,这已得到纠正。 Draft n3485 reads: 草案n3485内容如下:
[...] otherwise, the type of the function call expression is the return type of the statically chosen function (ie, ignoring the
virtual
keyword), even if the type of the function actually called is different. [...]否则,函数调用表达式的类型是静态选择函数的返回类型(即,忽略virtual
关键字),即使实际调用的函数的类型不同。 This return type shall be an object type, a reference type orcv
void
. 此返回类型应为对象类型,引用类型或cv
void
。
(my emphasis; not in your quote). (我的重点;不在你的引言中)。
The two paragraphs are now compatible; 这两段现在兼容; the (initial) type of the function call expression is now int &
, which gets adjusted to int
and value-category lvalue immediately. 函数调用表达式的(初始)类型现在是int &
,它立即调整为int
和value-category lvalue。 A similar process occurs with a function returning a qualified type, which has the advantage that we don't need to worry about lvalue-to-reference conversion: 返回一个限定类型的函数会发生类似的过程,这样做的好处是我们不需要担心左值到参考的转换:
const int g();
static_assert(std::is_same<decltype(g()), int>::value, "!!!");
The type of f()
is int
; f()
的类型是int
; its value category is lvalue. 它的价值类别是左值。 You can demonstrate this fact: 你可以证明这个事实:
int& f();
static_assert(std::is_same<int&,decltype((f()))>::value,"EXPLODE");
per C++11 §7.1.6.2 [dcl.type.simple]/4 "...if e
is an lvalue, decltype(e)
is T&
, where T
is the type of e
". 每个C ++11§7.1.6.2[dcl.type.simple] / 4“......如果e
是左值,则decltype(e)
是T&
,其中T
是e
的类型。
Example code: 示例代码:
int& foo() { static int x; return x; }
int bar() { return 0; }
template< class Type >
struct Is_ref_ { static const bool yes = false; };
template< class Type >
struct Is_ref_<Type&> { static const bool yes = true; };
#include <iostream>
using namespace std;
auto main() -> int
{
cout << boolalpha;
cout << "Function calls foo versus bar:" << endl;
cout << Is_ref_<decltype(foo())>::yes << endl;
cout << Is_ref_<decltype(bar())>::yes << endl;
int a;
int& b = a;
cout << endl;
cout << "lvalue versus ref:" << endl;
cout << Is_ref_<decltype(a)>::yes << endl;
cout << Is_ref_<decltype(b)>::yes << endl;
}
Output with Visual C++ 12.0 and with MinGW g++ 4.7.2: 使用Visual C ++ 12.0和MinGW g ++ 4.7.2输出:
Function calls foo versus bar: 函数调用foo与bar:
true 真正
false 假lvalue versus ref: 左值与参考值:
false 假
true 真正
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.