tornikeo
tornikeo

Reputation: 938

How does auto decide the type of variable?

#include <iostream>
int main() 
{
    auto n {42};
    cout << "The n has value of " << n <<
    " and a size of " << sizeof(n) << endl; // Works as expected
}
#include <iostream>
int main() 
{
    auto n = {42};
    cout << "The n has value of " << n <<
    " and a size of " << sizeof(n) << endl; // Does not work!
}

Why is that? In "A Tour of C++" it is explicitly said:

1.4.2 Initialization Before an object can be used, it must be given a value. C++ offers a variety of notations for expressing initialization, such as the = used above, and a universal form based on curly-brace delimited initializer lists:

    double d1 = 2.3; // initialize d1 to 2.3  
    double d2 {2.3}; // initialize d2 to 2.3  
    double d3 = {2.3}; // initialize d3 to 2.3 (the = is optional with { ... })
    complex<double> z2 {d1,d2};   
    complex<double> z3 = {d1,d2}; // the = is optional with { ... }  

The = is optional with {}.
so, why does this happen?

Upvotes: 1

Views: 221

Answers (3)

dfrib
dfrib

Reputation: 73166

This is governed by the rules of [dcl.type.auto.deduct], particularly [dcl.type.auto.deduct]/1 and [dcl.type.auto.deduct]/4 [emphasis mine]:

[dcl.type.auto.deduct]/1

Placeholder type deduction is the process by which a type containing a placeholder type is replaced by a deduced type.

[dcl.type.auto.deduct]/4

If the placeholder is the auto type-specifier, the deduced type T' replacing T is determined using the rules for template argument deduction. Obtain P from T by replacing the occurrences of auto with either a new invented type template parameter U or, if the initialization is copy-list-initialization, with std​::​initializer_­list<U>. Deduce a value for U using the rules of template argument deduction from a function call, where P is a function template parameter type and the corresponding argument is e. If the deduction fails, the declaration is ill-formed. Otherwise, T' is obtained by substituting the deduced U into P. [ Example:

auto x1 = { 1, 2 };    // decltype(x1) is std​::​initializer_­list<int>
auto x2 = { 1, 2.0 };  // error: cannot deduce element type
auto x3{ 1, 2 };       // error: not a single element
auto x4 = { 3 };       // decltype(x4) is std​::​initializer_­list<int>
auto x5{ 3 };          // decltype(x5) is int

 — end example ]

Your second example is using copy-list-initialization, meaning auto is replaced by, using the rules for template argument deduction, std::initializer_list<U>, where U is furthermore deduced as int.

auto n {42};    // deduced type is 'int'
auto m = {42};  // deduced type is 'std::initializer_list<int>'

These rules particularly apply to placeholder type deduction, and does thus not apply to the case of non-placeholder types; the latter example of the op already specifies the type and non type deduction applies.

// no placeholder type: type is 'double', and 'd1'
// through 'd3' simply uses different ways to initialize
// an object of (non-class fundamental) type 'double'.
double d1 = 2.3;   // copy initialization
double d2 {2.3};   // direct-list initialization; no narrowing allowed
double d3 = {2.3}; // copy-list-initialization (from C++11); no narrowing allowed

Upvotes: 2

t.niese
t.niese

Reputation: 40842

For both cases double d1 = {2.3}; and auto d2 = {2.3}; the {2.3} is an initlaizer list.

For double d3{2.3}; and auto d4{2.3}; the {2.3} is not an initializer list.

But for the first case, you specify for d1 what type it has, so the initializer list is used to set the value of d1. But for d2 you tell the compiler to choose the type, so it will be the initializer list.

So = is not optional, the difference is just not directly observable if you define the type for d1.

Upvotes: 0

tdao
tdao

Reputation: 17678

There is subtle difference between the two initialisation:

auto n {42};  // n is of type int

auto m = {42};  // m is of type initializer_list

What Is a Curly-Brace Enclosed List If Not an intializer_list?

typeid can be used to find the exact type of a variable, for example via typeid(x).name()

Upvotes: 1

Related Questions