Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The relationship between auto and decltype

Is

auto x = initializer; 

equivalent to

decltype(initializer) x = initializer; 

or

decltype((initializer)) x = initializer; 

or neither?

like image 528
fredoverflow Avatar asked Jul 29 '11 07:07

fredoverflow


People also ask

What is decltype used for?

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 )

Is decltype runtime or compile time?

decltype is a compile time evaluation (like sizeof ), and so can only use the static type.


1 Answers

decltype also considers whether the expression is rvalue or lvalue .

Wikipedia says,

The type denoted by decltype can be different from the type deduced by auto.

#include <vector> int main() {     const std::vector<int> v(1);     auto a = v[0];        // a has type int     decltype(v[0]) b = 1; // b has type const int&, the return type of                         // std::vector<int>::operator[](size_type) const     auto c = 0;           // c has type int     auto d = c;           // d has type int     decltype(c) e;        // e has type int, the type of the entity named by c     decltype((c)) f = c;  // f has type int&, because (c) is an lvalue     decltype(0) g;        // g has type int, because 0 is an rvalue } 

That pretty much explains the imporant difference. Notice decltype(c) and decltype((c)) are not same!

And sometime auto and decltype works together in a cooperative way, such as in the following example (taken from wiki, and modified a bit):

int& foo(int& i); float foo(float& f);  template <class T> auto f(T& t) −> decltype(foo(t))  {   return foo(t); } 

Wikipedia further explains the semantics of decltype as follows:

Similarly to the sizeof operator, the operand of decltype is unevaluated. Informally, the type returned by decltype(e) is deduced as follows:

  • If the expression e refers to a variable in local or namespace scope, a static member variable or a function parameter, then the result is that variable's or parameter's declared type
  • If e is a function call or an overloaded operator invocation, decltype(e) denotes the declared return type of that function
  • Otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e; if e is an rvalue, the result is T

These semantics were designed to fulfill the needs of generic library writers, while at the same time being intuitive for novice programmers, because the return type of decltype always matches the type of the object or function exactly as declared in the source code. More formally, Rule 1 applies to unparenthesized id-expressions and class member access expressions. For function calls, the deduced type is the return type of the statically chosen function, as determined by the rules for overload resolution. Example:

const int&& foo(); int i; struct A { double x; }; const A* a = new A(); decltype(foo()) x1; // type is const int&& decltype(i) x2; // type is int decltype(a->x) x3; // type is double decltype((a->x)) x4; // type is const double& 

The reason for the difference between the latter two invocations of decltype is that the parenthesized expression (a->x) is neither an id-expression nor a member access expression, and therefore does not denote a named object.Because the expression is an lvalue, its deduced type is "reference to the type of the expression", or const double&.

like image 69
Nawaz Avatar answered Sep 28 '22 00:09

Nawaz