Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 | страница 23
Как указано в комментарии, в этом случае вывод типа будет неудачным, но важно понимать, что на самом деле здесь имеют место два вывода типа. Один из них вытекает из применения ключевого слова >auto
: тип >x5
должен быть выведен. Поскольку инициализатор >x5
находится в фигурных скобках, тип >x5
должен быть выведен как >std::initializer_list
. Но >std::initializer_list
— это шаблон. Конкретизация представляет собой создание >std::initializer_list
с некоторым типом >Т
, а это означает, что тип >Т
также должен быть выведен. Такой вывод относится ко второй разновидности вывода типов — выводу типа шаблона. В данном примере этот второй вывод неудачен, поскольку значения в фигурных скобках не относятся к одному и тому же типу.
Рассмотрение инициализаторов в фигурных скобках является единственным отличием вывода типа >auto
от вывода типа шаблона. Когда объявленная с использованием ключевого слова >auto
переменная инициализируется с помощью инициализатора в фигурных скобках, выведенный тип представляет собой конкретизацию >std::initializer_list
. Но если тот же инициализатор передается шаблону, вывод типа оказывается неудачным, и код отвергается:
>auto x = { 11, 23, 9 }; // Тип x – std::initializer_list
>template
>void f(Т param); // эквивалентно объявлению x
>f({ 11, 23, 9 }); // Ошибка вывода типа для Т
Однако, если вы укажете в шаблоне, что >param
представляет собой >std::initializer_list
для некоторого неизвестного >Т
, вывод типа шаблона сможет определить, чем является >Т
:
>template
>void f(std::initializer_list<T> initList);
>f({ 11, 23, 9 }); // Вывод int в качестве типа Т, а тип
> // initList - std::initializer_list
Таким образом, единственное реальное различие между выводом типа >auto
и выводом типа шаблона заключается в том, что >auto
предполагает, что инициализатор в фигурных скобках представляет собой >std::initializer_list
, в то время как вывод типа шаблона этого не делает.
Вы можете удивиться, почему вывод типа >auto
имеет специальное правило для инициализаторов в фигурных скобках, в то время как вывод типа шаблона такого правила не имеет. Но я и сам удивлен. Увы, я не в состоянии найти убедительное объяснение. Но “закон есть закон”, и это означает, что вы должны помнить, что если вы объявляете переменную с использованием ключевого слова >auto
и инициализируете ее с помощью инициализатора в фигурных скобках, то выводимым типом всегда будет