Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7944 Discussions

ICL can't deduce variable type when a variable is declared using a placeholder type (auto) [bug since C++17]

Garipov__Ruslan
Beginner
563 Views

Intel C++ compiler 16 fails when compiles one of the following code:

int foo = 3;
auto boo {foo};
foo = boo + 1;

or

int foo;
auto boo {4};
foo = boo + 1;

ICL considers code ill-formed because:

error : no operator "+" matches these operands
        operand types are: std::initializer_list<int> + int
     foo = boo + 1;
               ^

Therefore it deduces type of `boo` to `std::initializer_list<int>`. This violates '7.1.6.4 auto specifier [dcl.spec.auto]':

7 When a variable declared using a placeholder type is initialized, or a return statement occurs in a function
declared with a return type that contains a placeholder type, the deduced return type or variable type is
determined from the type of its initializer. In the case of a return with no operand or with an operand of
type void, the declared return type shall be auto and the deduced return type is void. Otherwise, let T be
the declared type of the variable or return type of the function. If the placeholder is the auto type-specifier,
the deduced type is determined using the rules for template argument deduction. If the initialization is
direct-list-initialization then the braced-init-list shall contain only a single assignment-expression L.
If the
deduction is for a return statement and the initializer is a braced-init-list (8.5.4), the program is ill-formed.
Otherwise, 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 (14.8.2.1), where P is
a function template parameter type and the corresponding argument is the initializer, or L in the case of
direct-list-initialization
. If the deduction fails, the declaration is ill-formed. Otherwise, the type deduced for
the variable or return type is obtained by substituting the deduced U into P. [Example:

...

auto x5{ 3 }; // decltype(x5) is int
—end example ]

This becomes true since C++17, I believe. And for a compiler that doesn't support it, the behavior with code from above is OK. `boo` is `std::initializer_list<int>` in such case.

0 Kudos
1 Solution
Judith_W_Intel
Employee
563 Views

This recent language change is implemented in our 17.0 release (currently in beta).

Here's a description the change:

4/14/15 
C++14: Direct braced initializers and placeholder types

In C++11 mode, a variable declared with a placeholder type ("auto" or
"decltype(auto)") and with a "direct" braced initializer is deduced to have a
std::initializer_list<...> type.  In C++14 mode and in Microsoft C++ mode with
microsoft_version >= 1900, such cases are now only permitted if the braces
enclose a single element and in such situations the outer braces are ignored.
For example:

  auto x{ 1, 2 };  // std::initializer_list<int> in C++11 mode; now an error
                   // in C++14 mode.
  auto y{1};       // std::initializer_list<int> in C++11 mode; now int in
                   // C++14 mode.

This rule is a result of a language change introduced by the C++ standards
committee's paper N3922.

View solution in original post

0 Kudos
2 Replies
Judith_W_Intel
Employee
564 Views

This recent language change is implemented in our 17.0 release (currently in beta).

Here's a description the change:

4/14/15 
C++14: Direct braced initializers and placeholder types

In C++11 mode, a variable declared with a placeholder type ("auto" or
"decltype(auto)") and with a "direct" braced initializer is deduced to have a
std::initializer_list<...> type.  In C++14 mode and in Microsoft C++ mode with
microsoft_version >= 1900, such cases are now only permitted if the braces
enclose a single element and in such situations the outer braces are ignored.
For example:

  auto x{ 1, 2 };  // std::initializer_list<int> in C++11 mode; now an error
                   // in C++14 mode.
  auto y{1};       // std::initializer_list<int> in C++11 mode; now int in
                   // C++14 mode.

This rule is a result of a language change introduced by the C++ standards
committee's paper N3922.

0 Kudos
Garipov__Ruslan
Beginner
563 Views
Thanks a lot! I'm looking forward for the new version!
0 Kudos
Reply