decltype in c+0x and parentheses

1
2
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct A
{
  A(){}
};
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!
Last edited on
Line 19 declares a function. This is colloquially known as "Most Vexing Parse" (see Effective C++ or just google.
Line 20 declares an object. The parentheses are a common way to avoid MVP.

Decltype has nothing to do with this. MVP is a C++98 feature.
Last edited on
> B<A> b1(A());

A() is a type (nullary function returning A)
( A() ) is not a type; it is an expression (because of the parenthesis around it)

In C++11, disambiguation is easy if we use the uniform initialization syntax:

1
2
3
B<A> b1 { A() } ; // A() can't be a type here

decltype( A() ) x ; // here too, A() can't be a type 

Thanks for your help. But how to understand “The inner parentheses cause the statement to be evaluated as an expression instead of a member access”.
Does it need to be treated as a rule?
> “The inner parentheses cause the statement to be evaluated as an expression instead of a member access”.
> Does it need to be treated as a rule

I suppose so. Or else, the parsing precedence rules would apply.
1
2
3
4
5
6
char srce[] = "hello world" ;
char dest[100] ;
std::strcpy( dest, srce ) ; // ok, call of std::strcpy with two arguments

std::strcpy( ( dest, srce ) ) ; // ***error, call of std::strcpy with only one argument
// ( dest, srce ) is an expression; (in which the comma is the sequencing operator) 
Last edited on
Here is the other situation:
1
2
3
4
5
bool func(){
    return false;
}

decltype((func())) ;    // bool, parentheses around f() are ignored 

I am a little confused.
> bool, parentheses around f() are ignored

Yes, because in decltype(e), e is always evaluated as an expression.

In decltype(expression),
if expression is a function call or an invocation of an overloaded operator (parentheses around expression are ignored), decltype(expression) is the return type of the statically chosen function.


For several annotated examples: http://pic.dhe.ibm.com/infocenter/comphelp/v111v131/topic/com.ibm.xlcpp111.aix.doc/language_ref/decltype.html
in your link,for "General rules for using decltype" says, an expression only match the 3rd rule can make itself to T&,
but for:
1
2
int i=6;
decltype((i)); //reference type 


i cannot see how do it match the 3rd rule .
The type denoted by decltype(e) is defined as follows:

rule 1: if e is an unparenthesized id-expression or an unparenthesized class member access, decltype(e) is the type of the entity named by e.

rule 2: otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;

rule 3: otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;

rule 4: otherwise, decltype(e) is the type of e.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int i = 9 ;
int foo() ; // function returning int

decltype(i) a ; // i is is an unparenthesized id-expression
// rule 1. type of 'a' is 'int'

decltype( ++i ) b = i ; // the expression ++i is an an lvalue of type 'int'
// rule 3. type of 'b' is 'reference to int'
// note: like in sizeof(++i), ++i is not evaluated at run-time

decltype( (i) ) c = i ; // the expression (i) is an an lvalue of type 'int'
// rule 3. type of 'c' is 'reference to int'

decltype( foo() ) d ; // the expression foo() is an an rvalue of type 'int'
// rule 4. type of 'd' is 'int'
// note: like in sizeof( foo() ), foo() is not evaluated at run-time

decltype( ( foo() ) ) e ; // the expression ( foo() ) is an an rvalue of type 'int'
// rule 4. type of 'e' is 'int'
// note: foo() is not evaluated at run-time

decltype( +i ) f ; // the expression +i is an an rvalue of type 'int'
// rule 4. type of 'f' is 'int'

decltype( (+i) ) g ; // the expression (+i) is an an rvalue of type 'int'
// rule 4. type of 'g' is 'int'

decltype( std::move(i) ) h = i+3 ; // the expression std::move(i) is an xvalue of type 'int'
// rule 2. type of 'h' is 'rvalue-reference to int' 

decltype( ++i ) b = i ; ++i is an expression and unparenthesized why should it match the rule 1?

And I know so little that I do not know the expression of '+i'.What‘s the significance of this expression
Last edited on
++i is not an id-expression
+i is (for built-in operator+) the decayed and promoted i.
Last edited on
Is ’+i‘ ‘s left operand 0 ?
In +i, the + is the unary plus operator.

With short s = 0 ;, +s is an rvalue of type int. The unary + operator always applies promotions where applicable and always yields an rvalue.
Thank you for helping to solve all the puzzles .I appreciate that very much.
Topic archived. No new replies allowed.