Initialization of variables in C++ can have several forms:
- default initialization: std::string s;
- value initialization: std::string s{};
- direct initialization: std::string s("demo");
- copy initialization: std::string s = "demo";
- list initialization: std::string s{'d', 'e', 'm', 'o'};
- aggregate initialization: char s[5] = {'d', 'e', 'm', 'o'};
- reference initialization: char& c = s[0];
C++11 introduced a generalized syntax for initialization with a braced initializer list, referred to as braced-init-list. Initialization with braced-init-list is called list initialization. There are two types of list initialization, each having multiple forms (check the above links), but simplified, we can have:
- direct list initialization: T object {arg1, arg2, ...};
- copy list initialization: T object = {arg1, arg2, ...};
Prior to C++17 the type for all the following objects (a, b, c and d) is deduced to std::initializer_list<int>. There is no difference between the direct-list-initialization and the copy-list-initialization on the result of the type deduction.
auto a = {42}; // std::initializer_list<int> auto b {42}; // std::initializer_list<int> auto c = {1, 2}; // std::initializer_list<int> auto d {1, 2}; // std::initializer_list<int>
This, however, changed in C++17 that introduced the following rules:
- for copy list initialization auto deduction will deduce a std::initializer_list<T> if all elements in the list have the same type, or be ill-formed.
- for direct list initialization auto deduction will deduce a T if the list has a single element, or be ill-formed if there is more than one element.
As a result, the example above changes so that a and c are still std::initializer_list<int> but b is deduced as an int and d is ill-formed, because there is more than one value in the brace-init-list.
auto a = {42}; // std::initializer_list<int> auto b {42}; // int auto c = {1, 2}; // std::initializer_list<int> auto d {1, 2}; // error, too many
For more information about these changes see N3922: New Rules for auto deduction from braced-init-list.
So currently clang and gcc apply this change to C++11 and C++14, see Wandbox for latest versions of both: https://wandbox.org/ . The proposal noted that this was considered a C++14 defect and clangs status for N3922: http://clang.llvm.org/cxx_status.html#n3922 says:
“This is a backwards-incompatible change that is applied to all language versions that allow type deduction from auto (per the request of the C++ committee)”
Important to note for those using older compilers since there was implementation divergence here for a bit of time and this caused confusion for some as we can see from this Stackoverflow question: http://stackoverflow.com/q/31301369/1708801
Shafik Yaghmour , just follow the C++ committee of the request and do ont use C++14
My C++11/14 compiler
for the line
auto d {1, 2}; // std::initializer_list
giving the error
C:\Users\Vishnu\Desktop\cpp14.cpp|11|error: direct-list-initialization of ‘auto’ requires exactly one element [-fpermissive]|
From your explanation I thought I will see this error in only C++17, but I am seeing in 11 and 14 as well.