1

Possible Duplicate:
decltype and parenthesis

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

i just didn't understand why 'i' which is in parentheses is regarded as Lvalue, now, i knew the application of the parentheses until i found that in MSDN:The inner parentheses cause the statement to be evaluated as an expression instead of a member access.(http://msdn.microsoft.com/en-us/library/dd537655.aspx), and i also didn't understand a question i didn't comprehend for a long time.

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;   
}

Why A() is regarded as anonymous object when put it in parentheses as (A()). the inner parentheses explanation about decltype in MSDN can't apply to this situation. could someone tell me that is there a expanation about the parentheses function in this two situation in C++ standard. How should i understand this better, appreciate it very much!

Community
  • 1
  • 1
Leonhart Squall
  • 810
  • 1
  • 7
  • 15
  • 1
    The second part of the question is [the vexing parse](http://en.wikipedia.org/wiki/Most_vexing_parse). – jpalecek Jun 08 '12 at 12:15

1 Answers1

2

Those are really completely different situations.

B<A> b1(A());

This is a function declaration because it follows the syntax production "return-type identifier '(' parameter-declaration-list ')'", where parameter-declaration-list is a comma-separated list of parameter-declarations. The production for such a declaration is "type abstract-declarator[opt]". An abstract-declarator can, among other things, be empty, or "'(' abstract-declarator ')'". So "A()" matches a type (A) followed by the parentheses form of abstract-declarator containing the empty form of abstract-declarator. Thus, the code is syntactically a valid function declaration and is parsed as such.

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

Here, if we want to go the function declaration route, we need to match "(A())" to parameter-declaration; however, there is no way to do this. So this isn't a function declaration, and therefore must be a variable declaration with a direct-initializer.

The other situation is grammatically unambiguous. Both decltype(i) and decltype((i)) are simple decltype derivations. In the first case, the syntax tree is DeclType( DeclRefExpression("i") ), in the second, it's DeclType( ParenExpression( DeclRefExpression("i") ) ).

The special part here are the rules for decltype. The decltype rules are as follows:

  1. If the expression is a function call, the result of decltype is the declared type of that function. E.g. given "int foo()", decltype(foo()) is "int". Given "int& foo()", decltype(foo()) is "int&".
  2. If the expression is a declaration reference expression, the result of decltype is the declared type of that declaration. Given "int i", decltype(i) is "int". Given "int& i", decltype(i) is "int&".
  3. If neither of the above applies and the expression is an lvalue, the result of decltype is an lvalue reference to the type of the expression. If the expression is an lvalue of type int, the result is "int&".
  4. If none of the above rules apply, the result of decltype is the type of the expression. If the expression is an rvalue of type int, the result is "int".

In decltype(i), the expression is a declref to i. The type of i is int. Thus, decltype(i) is "int". In decltype((i)), the expression is a parenexpr. It doesn't matter what the parentheses contain - neither rule 1 nor 2 can apply. However, (i) is an lvalue, so rule 3 applies. The type of (i) is int, so decltype((i)) is "int&".

stefaanv
  • 14,072
  • 2
  • 31
  • 53
Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157