How to automatically deduce a type?

I have some use cases for auto :

 auto s = expr; //s is always lvalue auto & s = expr; //s is always lvalue reference? What if expr is rvalue? auto && s = expr; //s is perfectly forwarded 

Are they true? If not, why?

+4
source share
2 answers

dyp is correct, and I would like to clarify.

First of all, the output consists of dyp:

The type displayed for auto in the variable declaration is determined according to the rules for outputting template arguments, see [dcl.spec.auto] / 6; with one exception: if the initializer is a list bound to init-init, the type being deduced is std::initializer_list .

I will explain.

First of all,

 auto s = expr; 

This is the same as the output of T from expr ,

 template<class T> void f(T s); f(expr); 

The rule for deriving a template argument is rather complicated, since you only relate to lvalue and rvalue materials, let's focus on this.

The template argument is output by comparing the type of the template parameter (let's call it P , in this case P is T ) and the corresponding argument (let's call it A , in this case the type is expr ).

From 14.8.2.1,

If P is not a reference type:

- If A is an array type, the pointer type created by the standard transformation (4.2) is used instead of A to infer the type; otherwise,

- If A is a function type, the pointer type created by the standard conversion of the-to-pointer function (4.3) is used instead of A to infer the type; otherwise,

- If A is a class with qualification cv, the upper levels of cv qualifiers of type As are ignored for type inference.

So, if expr is an array or function, it will be considered as pointers, if expr has cv qualification ( const , etc.), they will be ignored.

If P is a cv-qualified type, then top-level cv-qualifiers of type P s are ignored for type inference.

It actually says:

 const auto s = expr; 

s is a const variable, but for type inference for auto purposes, const will be removed.

Thus, the expr type will be inferred from the above auto rules (after some type conversion indicated above).

Note that when an expression is a reference to T , it will be set to T before the previous analysis.

Thus, any type expr - rvalue, lvalue or lvalue / rvalue ref - type auto will always be type expr without reference.

 auto s1 = 1; //int int &x = s1; auto s2 = x; //int int &&y = 2; auto s3 = y; //int 

Secondly, let's see

 auto &s = expr; 

It will be the same as

 template<class T> void f(T &s); f(expr); 

An additional rule from the standard is as follows:

If P is a reference type, the type denoted by P is used to infer the type.

Thus, the output of auto will be the same as without & , but after subtracting the type auto , & added to the end of auto .

 //auto &s1 = 1; //auto is deducted to int, int &s1 = 1, error! const auto &s1 = 1; //auto is deducted to int, const int &s1 = 1; ok! const int &x = s1; auto &s2 = x; //auto is int, int &s2 = x; ok! int &&y = 2; auto &s3 = y; //auto is int, int &s3 = y; ok! 

Note that the last y is an lvalue. C ++ rule: rvalue reference name is an lvalue.

Finally:

 auto &&s = expr; 

It is without a doubt the same as

 template<class T> void f(T &&s); f(expr); 

One additional rule:

If P is the rvalue reference to the cv-unqualified template parameter and the argument is lvalue, the type "lvalue reference to A" is used in place A to type in.

This actually means that if expr is an rvalue, the rule will be the same as the second case (lvalue case), but if expr is an lvalue, type A will be a lvalue reference to A

The remark from the previous one is explained, A never refers, because the type of expression is never a reference. But for this special case ( auto && and A is an lvalue), it is necessary to use a reference to A , regardless of whether expr itself is a reference type or not.

Example:

 auto &&s1 = 1; //auto is deducted to int, int &&s1 = 1, ok! int x = 1; auto &&s2 = x; //x is lvalue, so A is int &, auto is deducted to int &, int & &&s2 = x; ok! int &&y = 2; auto &&s3 = y; //y is lvalue, auto is int &, int & &&s3 = y; ok! 
+5
source

Since no one gives an answer, and I understand now (thanks @dyp), I will simply post the answer. Indicate the error, if any:

 auto s = expr; 

If expr is an lvalue, prvalue, or any reference, s always an lvalue and is copied.

 auto& s = expr; 

If expr is the value of lvalue, lvalue reference or rvalue reference, s is the value of lvalue. If expr is the value of prvalue, it is an error and is not legal.

 auto&& s = expr; 

s perfectly redirected (rvalue will become a rvalue reference and collapse).

0
source

Source: https://habr.com/ru/post/1013798/


All Articles