C++ auto keyword. Why is it magic?

C++TypesC++11Auto

C++ Problem Overview


From all the material I used to learn C++, auto has always been a weird storage duration specifier that didn't serve any purpose. But just recently, I encountered code that used it as a type name in and of itself. Out of curiosity I tried it, and it assumes the type of whatever I happen to assign to it!

Suddenly STL iterators and, well, anything at all that uses templates is 10 fold easier to write. It feels like I'm using a 'fun' language like Python.

Where has this keyword been my whole life? Will you dash my dreams by saying it's exclusive to visual studio or not portable?

C++ Solutions


Solution 1 - C++

auto was a keyword that C++ "inherited" from C that had been there nearly forever, but virtually never used because there were only two possible conditions: either it wasn't allowed, or else it was assumed by default.

The use of auto to mean a deduced type was new with C++11.

At the same time, auto x = initializer deduces the type of x from the type of initializer the same way as template type deduction works for function templates. Consider a function template like this:

template<class T>
int whatever(T t) { 
    // point A
};

At point A, a type has been assigned to T based on the value passed for the parameter to whatever. When you do auto x = initializer;, the same type deduction is used to determine the type for x from the type of initializer that's used to initialize it.

This means that most of the type deduction mechanics a compiler needs to implement auto were already present and used for templates on any compiler that even sort of attempted to implement C++98/03. As such, adding support for auto was apparently fairly easy for essentially all the compiler teams--it was added quite quickly, and there seem to have been few bugs related to it either.

When this answer was originally written (in 2011, before the ink was dry on the C++ 11 standard) auto was already quite portable. Nowadays, it's thoroughly portable among all the mainstream compilers. The only obvious reasons to avoid it would be if you need to write code that's compatible with a C compiler, or you have a specific need to target some niche compiler that you know doesn't support it (e.g., a few people still write code for MS-DOS using compilers from Borland, Watcom, etc., that haven't seen significant upgrades in decades). If you're using a reasonably current version of any of the mainstream compilers, there's no reason to avoid it at all though.

More recent revisions of the standard have added a few new places that auto can be used. Starting with C++14, you can use auto for the type of a parameter to a lambda:

    [](auto s) { return s + 1; }

This does essentially the same thing as the example above--even though it doesn't explicitly use template syntax, this is basically a template that deduces the type of the parameter, and instantiates the template over that type.

That was convenient and useful enough that in C++20, the same capability was added for normal functions, not just lambdas.

But, just as before all of this really comes down to using the same basic type deduction mechanism as we've had for function templates since C++98. auto allows that to be used in more places, and more conveniently, but the underlying heavy lifting remains the same.

Solution 2 - C++

It's just taking a generally useless keyword and giving it a new, better functionality. It's standard in C++11, and most C++ compilers with even some C++11 support will support it.

Solution 3 - C++

For variables, specifies that the type of the variable that is being declared will be automatically deduced from its initializer. For functions, specifies that the return type is a trailing return type or will be deduced from its return statements (since C++14).

Syntax

auto variable initializer	(1)	(since C++11)

auto function -> return type	(2)	(since C++11)

auto function	(3)	(since C++14)

decltype(auto) variable initializer	(4)	(since C++14)

decltype(auto) function	(5)	(since C++14)

auto ::	(6)	(concepts TS)

cv(optional) auto ref(optional) parameter	(7)	(since C++14)

Explanation

  1. When declaring variables in block scope, in namespace scope, in initialization statements of for loops, etc., the keyword auto may be used as the type specifier.

    Once the type of the initializer has been determined, the compiler determines the type that will replace the keyword auto using the rules for template argument deduction from a function call (see template argument deduction#Other contexts for details). The keyword auto may be accompanied by modifiers, such as const or &, which will participate in the type deduction. For example, given const auto& i = expr;, the type of i is exactly the type of the argument u in an imaginary template template<class U> void f(const U& u) if the function call f(expr) was compiled. Therefore, auto&& may be deduced either as an lvalue reference or rvalue reference according to the initializer, which is used in range-based for loop.

    If auto is used to declare multiple variables, the deduced types must match. For example, the declaration auto i = 0, d = 0.0; is ill-formed, while the declaration auto i = 0, *p = &i; is well-formed and the auto is deduced as int.

  2. In a function declaration that uses the trailing return type syntax, the keyword auto does not perform automatic type detection. It only serves as a part of the syntax.

  3. In a function declaration that does not use the trailing return type syntax, the keyword auto indicates that the return type will be deduced from the operand of its return statement using the rules for template argument deduction.

  4. If the declared type of the variable is decltype(auto), the keyword auto is replaced with the expression (or expression list) of its initializer, and the actual type is deduced using the rules for decltype.

  5. If the return type of the function is declared decltype(auto), the keyword auto is replaced with the operand of its return statement, and the actual return type is deduced using the rules for decltype.

  6. A nested-name-specifier of the form auto:: is a placeholder that is replaced by a class or enumeration type following the rules for constrained type placeholder deduction.

  7. A parameter declaration in a lambda expression. (since C++14) A function parameter declaration. (concepts TS)

Notes

Until C++11, auto had the semantic of a storage duration specifier. Mixing auto variables and functions in one declaration, as in auto f() -> int, i = 0; is not allowed.

For more info : http://en.cppreference.com/w/cpp/language/auto

Solution 4 - C++

This functionality hasn't been there your whole life. It's been supported in Visual Studio since the 2010 version. It's a new C++11 feature, so it's not exclusive to Visual Studio and is/will be portable. Most compilers support it already.

Solution 5 - C++

The auto keyword is an important and frequently used keyword for C ++.When initializing a variable, auto keyword is used for type inference(also called type deduction).

There are 3 different rules regarding the auto keyword.

First Rule

auto x = expr; ----> No pointer or reference, only variable name. In this case, const and reference are ignored.

int  y = 10;
int& r = y;
auto x = r; // The type of variable x is int. (Reference Ignored)

const int y = 10;
auto x = y; // The type of variable x is int. (Const Ignored)

int y = 10;
const int& r = y;
auto x = r; // The type of variable x is int. (Both const and reference Ignored)

const int a[10] = {};
auto x = a; //  x is const int *. (Array to pointer conversion)

Note : When the name defined by auto is given a value with the name of a function,
       the type inference will be done as a function pointer.
Second Rule

auto& y = expr; or auto* y = expr; ----> Reference or pointer after auto keyword.

Warning : const is not ignored in this rule !!! .

int y = 10;
auto& x = y; // The type of variable x is int&.

Warning : In this rule, array to pointer conversion (array decay) does not occur !!!.

auto& x = "hello"; // The type of variable x is  const char [6].

static int x = 10;
auto y = x;	// The variable y is not static.Because the static keyword is not a type. specifier 
            // The type of variable x is int.
Third Rule

auto&& z = expr; ----> This is not a Rvalue reference.

Warning : If the type inference is in question and the && token is used, the names introduced like this are called "Forwarding Reference" (also called Universal Reference).

auto&& r1 = x; // The type of variable r1 is int&.Because x is Lvalue expression. 

auto&& r2 = x+y; // The type of variable r2 is int&&.Because x+y is PRvalue expression. 

Solution 6 - C++

The auto keyword specifies that the type of the variable that is being declared will be automatically deducted from its initializer. In case of functions, if their return type is auto then that will be evaluated by return type expression at runtime.

It can be very useful when we have to use the iterator. For e.g. for below code we can simply use the "auto" instead of writing the whole iterator syntax .

int main() 
{ 

// Initialize set 
set<int> s; 

s.insert(1); 
s.insert(4); 
s.insert(2); 
s.insert(5); 
s.insert(3); 

// iterator pointing to 
// position where 2 is 
auto pos = s.find(3); 

// prints the set elements 
cout << "The set elements after 3 are: "; 
for (auto it = pos; it != s.end(); it++) 
    cout << *it << " "; 

return 0; 
}

This is how we can use "auto" keyword

Solution 7 - C++

It's not going anywhere ... it's a new standard C++ feature in the implementation of C++11. That being said, while it's a wonderful tool for simplifying object declarations as well as cleaning up the syntax for certain call-paradigms (i.e., range-based for-loops), don't over-use/abuse it :-)

Solution 8 - C++

It's Magic is it's ability to reduce having to write code for every Variable Type passed into specific functions. Consider a Python similar print() function in it's C base.

#include <iostream>
#include <string>
#include <array>

using namespace std;

void print(auto arg) {
     cout<<arg<<" ";
}

int main()
{
  string f = "String";//tok assigned
  int x = 998;
  double a = 4.785;
  string b = "C++ Auto !";
//In an opt-code ASCII token stream would be iterated from tok's as:
  print(a);
  print(b);
  print(x);
  print(f);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAnne QuinnView Question on Stackoverflow
Solution 1 - C++Jerry CoffinView Answer on Stackoverflow
Solution 2 - C++Nicol BolasView Answer on Stackoverflow
Solution 3 - C++Prathamesh AwareView Answer on Stackoverflow
Solution 4 - C++R. Martinho FernandesView Answer on Stackoverflow
Solution 5 - C++east1000View Answer on Stackoverflow
Solution 6 - C++rahul goyalView Answer on Stackoverflow
Solution 7 - C++JasonView Answer on Stackoverflow
Solution 8 - C++rodeone2View Answer on Stackoverflow