8

According to the C++ Primer, C++ arrow operator yields an lvalue. Additionally decltype of an expression which yields an lvalue will result in a reference type. So why the following decltype does not result in a reference type.

struct MyStruct {
   string name
};
MyStruct s;
s.name = "aname";
MyStruct* p = &s;
decltype (p -> name) str = s.name; //type of str will be string and not &string although p -> name yields an lvalue
Nami
  • 1,215
  • 11
  • 21

2 Answers2

9

From cppreference

If the argument is an unparenthesized id-expression or an unparenthesized class member access, then decltype yields the type of the entity named by this expression. If there is no such entity, or if the argument names a set of overloaded functions, the program is ill-formed.

This is the case in your example, so it will return the underlying type of the member, which is a std::string.

If you want, you can add parenthesis so that decltype results in a reference:

//'str' is a std::string&
decltype((p->name)) str = s.name;
Rakete1111
  • 47,013
  • 16
  • 123
  • 162
5

From decltype (which is from §7.1.6.2/4 [dcl.type.simple]):

If the argument is an unparenthesized id-expression or an unparenthesized class member access, then decltype yields the type of the entity named by this expression.

p->name falls in the above case, so the type of decltype(p->name) is the type of p->name which is std::string not std::string&.

On the other hand, decltype((p->name)) is std::string& because (p->name) is an lvalue expression.

Holt
  • 36,600
  • 7
  • 92
  • 139