Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does `decltype` give me an object's static type, or its runtime type?

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

  • if e is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;
  • otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;
  • otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
  • otherwise, decltype(e) is the type of e.

The operand of the decltype specifier is an unevaluated operand (Clause 5).

The second, third and fourth cases clearly refer to the type of the expression, which would not include any polymorphism considerations.

However, and I'm not entirely sure what "entity" means here, the first case appears to be naming the object refered to by the expression e. It is ambiguous to me as to whether "the type of the entity" means its runtime type, or its static type.

like image 654
Lightness Races in Orbit Avatar asked Apr 09 '13 10:04

Lightness Races in Orbit


2 Answers

It's actually impossible to run into this problem, due to the restraints of that first case.

Consider:

struct A     {};
struct B : A {};

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

The use of * makes us fall through to the third case.

And for references?

struct A     {};
struct B : A {};

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

x is a reference with type A&, and it is this "entity" whose type results.

The only way to use the first case is by directly naming an object, and we cannot do that in a way that hides a runtime type:

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

This is why, according to these answers, it is always the static type of an object that is used.

like image 145
Lightness Races in Orbit Avatar answered Sep 27 '22 21:09

Lightness Races in Orbit


You don't have to look into the individual points: the results of decltype are a type known to the compiler, which pretty much excludes any dynamic typing. And the last line that you quote couldn't be more explicit: the specifier is not evaluated, which also excludes any dynamic typing.

like image 34
James Kanze Avatar answered Sep 27 '22 21:09

James Kanze