Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ why decltype(*pointer) yields a reference?

I wanted to know why, when I use decltype (* pointer), it defines the type of the variable as a reference. For example:

int i = 42, * p = & i;
decltype (* p) c = i;

Now c is a reference (linked to i). Why is it a reference and not an integer? I'm reading the book Cpp Primer 5th. Edition. P. 110 says this and I do not understand why.

like image 310
Luiz Fernando Avatar asked Jul 17 '18 19:07

Luiz Fernando


People also ask

What does decltype return?

The decltype type specifier yields the type of a specified expression. The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to declare a function template whose return type depends on the types of its template arguments.

Why to use decltype?

You should use decltype when you want a new variable with precisely the same type as the original variable. You should use auto when you want to assign the value of some expression to a new variable and you want or need its type to be deduced.

What does decltype in c++?

In the C++ programming language, decltype is a keyword used to query the type of an expression. Introduced in C++11, its primary intended use is in generic programming, where it is often difficult, or even impossible, to express types that depend on template parameters.

What does decltype stand for?

Decltype keyword in C++ Decltype stands for declared type of an entity or the type of an expression. It lets you extract the type from the variable so decltype is sort of an operator that evaluates the type of passed expression. SYNTAX : decltype( expression )


2 Answers

Contrary to apparently popular belief, *p has type int. From [expr.unary.op]

The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. If the type of the expression is “pointer to T”, the type of the result is “T”.

The reason decltype(*p) yields int& is because of how decltype works. From [dcl.type.simple]

For an expression e, the type denoted by decltype(e) is defined as follows: [...]

  • otherwise, if e is an unparenthesized id-expression or an unparenthesized class member access, 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; [...]

Here id-expression means an expression exactly consisting of a possibly parenthesized name.

Since *p is an lvalue expression of type int and not an unparenthesized id-expression nor class member access, the third bullet applies and decltype(*p) is int&.

It is worthy to note i is an unparenthesized id-expression, therefore the first bullet applies and decltype(i) is int.

like image 195
Passer By Avatar answered Oct 09 '22 11:10

Passer By


The type that decltype(expr) will give you depends on the value category of the expression. If expr is not just an id-expression (i.e. directly the name of a thing), then the rules basically are:

  • If expr is an xvalue of type T, then decltype(expr) will be T&&.
  • If expr is an lvalue of type T, then decltype(expr) will be T&.
  • Otherwise, decltype(expr) will be T.

In your case, *p is an lvalue of type int. Thus decltype(*p) is defined to be int&. If you want decltype to give you int, you'll have to make the expression be a prvalue, for example by applying the unary + operator like suggested by @Cheers and hth. - Alf in his comment above. However, such arcane constructions might better be avoided in real code. For the sake of readability it might be better to just use std::remove_reference_t<decltype(*p)>.

like image 26
Michael Kenzel Avatar answered Oct 09 '22 11:10

Michael Kenzel