Эффективный и современный С++. 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 и инициализируете ее с помощью инициализатора в фигурных скобках, то выводимым типом всегда будет