1

可能重复:
decltype 和括号

int i=6;
decltype((i)) var5 = i;      // int& 

我只是不明白为什么括号中的“i”被视为左值,现在,我知道括号的应用,直到我在 MSDN 中发现:内括号导致语句被评估为表达式而不是会员访问。(http://msdn.microsoft.com/en-us/library/dd537655.aspx),我也没有理解一个我很久没有理解的问题。

template<typename T>
class B
{
public:
    B(T t){printf("B\n");}

};
template <typename T >
void ft(T t)
{
    t.f();
}
int _tmain(int argc, _TCHAR* argv[])
{
    B<A> b1(A());   //one function declaration, A() is regarded as fun-ptr, and b1 is a function
    B<A> b2((A())); //A() is regarded as anonymous object.
    return 0;   
}

为什么A()放在括号中时被视为匿名对象(A())。MSDN中关于decltype的内括号解释不适用于这种情况。有人可以告诉我,在 C++ 标准的这两种情况下,是否有关于括号函数的扩展。我该如何更好地理解这一点,非常感谢!

4

1 回答 1

2

这些是完全不同的情况。

B<A> b1(A());

这是一个函数声明,因为它遵循语法产生式“return-type identifier '(' parameter-declaration-list ')'”,其中 parameter-declaration-list 是以逗号分隔的参数声明列表。这种声明的产生是“type abstract-declarator[opt]”。一个抽象声明符可以是空的,或者是“'('abstract-declarator ')'”。因此,“A()”匹配类型 (A),后跟括号形式的抽象声明符,其中包含空形式的抽象声明符。因此,代码在语法上是一个有效的函数声明,并被解析。

B<A> b1((A()));

在这里,如果我们要走函数声明路线,我们需要将“(A())”匹配到参数声明;但是,没有办法做到这一点。所以这不是函数声明,因此必须是带有直接初始化程序的变量声明。

另一种情况在语法上是明确的。decltype(i) 和 decltype((i)) 都是简单的 decltype 派生。在第一种情况下,语法树是 DeclType( DeclRefExpression("i") ),在第二种情况下,它是 DeclType( ParenExpression( DeclRefExpression("i") ) )。

这里的特殊部分是 decltype 的规则。decltype 规则如下:

  1. 如果表达式是函数调用,则 decltype 的结果是该函数的声明类型。例如,给定“int foo()”,decltype(foo()) 是“int”。给定“int& foo()”,decltype(foo()) 是“int&”。
  2. 如果表达式是声明引用表达式,则 decltype 的结果是该声明的声明类型。给定“int i”,decltype(i) 是“int”。给定“int& i”,decltype(i) 是“int&”。
  3. 如果以上都不适用并且表达式是左值,则 decltype 的结果是对表达式类型的左值引用。如果表达式是 int 类型的左值,则结果为“int&”。
  4. 如果上述规则均不适用,则 decltype 的结果是表达式的类型。如果表达式是 int 类型的右值,则结果为“int”。

在 decltype(i) 中,表达式是 i 的 declref。i 的类型是 int。因此,decltype(i) 是“int”。在 decltype((i)) 中,表达式是一个 parenexpr。括号包含什么并不重要——规则 1 和 2 都不能适用。但是,(i) 是左值,因此适用规则 3。(i) 的类型是 int,所以 decltype((i)) 是 "int&"。

于 2012-06-08T12:23:54.377 回答