Does `decltype` tell me the static type of the object or its runtime type?

[C++11: 7.1.6.2/4]: type indicated by decltype(e) is defined as follows:

  • if e is an non-incremental id expression or unparenthesized class member access (5.2.5), decltype(e) is a type of object named e . If such an object is absent or if e calls a set of overloaded functions, the program is poorly formed;
  • otherwise, if e is the value of x, decltype(e) is T&& , where T is the type of e ;
  • otherwise, if e is an lvalue, decltype(e) is T& , where T is a type of e ;
  • otherwise decltype(e) is type e .

The decltype specifier operand is an unvalued operand (clause 5).

The second, third, and fourth cases clearly relate to a type of expression that would not include any considerations of polymorphism.

However, and I'm not quite sure what “entity” means here, the first case seems to indicate the object referenced by the expression e . It is ambiguous for me to talk about whether an “object type” means its run-time type or its static type.

+11
c ++ language-lawyer c ++ 11 decltype
Apr 09 '13 at 10:21
source share
3 answers

It is actually impossible to deal with this problem due to the limitations of this first case.

Consider:

 struct A {}; struct B : A {}; int main() { A* x = new B(); // What is `decltype(*x)`? } 

Using * makes us fail in the third case.

And for the links?

 struct A {}; struct B : A {}; int main() { A& x = *(new B()); // What is `decltype(x)`? } 

x is a reference of type A& , and it is this “entity” that has the result type.

The only way to use the first case is the direct name of the object, and we cannot do it in such a way as to hide the type of runtime:

 struct A {}; struct B : A { void foo() {} }; int main() { A x = B(); // well, you've sliced it now, innit? decltype(x) y; y.foo(); // error: 'struct A' has no member named 'foo' } 

That is why, according to these answers , it is always a static type of object used.

+9
Apr 09 '13 at 10:21
source share

You do not need to look at individual moments: the results from decltype are a type known to the compiler that pretty much excludes any dynamic typing. And the last line that you quote cannot be more explicit: the specifier is not evaluated, which also excludes any dynamic typing.

+5
Apr 09 '13 at 11:26
source share

Basically the question is what “entity” means here (possible values ​​are defined in section 3). Consider

 struct A { int a; }; int main() { A a = {}; const A b = {}; const A *aptr = (rand() % 42) ? &a : &b; decltype(aptr->a) x = 0; decltype((aptr->a)) y = 0; } 

Is x type of const int or int ? If you take an entity to mean “member”, it is int because the member A::a is of type int . If you take the object "object" of the object, the type will be either const int or int , depending on the result of rand() . Objects, their existence, and properties (including their type as a whole) are a run-time problem.

I say this is not real ambiguity. Because everyone knows what is meant, and because the Standard uses the phrase “named by e” rather than “indicated by the letter e” or “indicated by the letter e”, indicating that only search results by name .

Note that the type of y always const int& , because the type of the expression aptr->a is equal to const int and this value is l.

0
Apr 09 '13 at 17:00
source share



All Articles