Ответ 1
Ваша первая строка printme({'a', 'b', 'c'})
является незаконной, поскольку аргумент шаблона T
не может быть выведен. Если вы явно укажете аргумент шаблона, он будет работать, например. printme<vector<char>>({'a', 'b', 'c'})
или printme<initializer_list<char>>({'a', 'b', 'c'})
.
Другие, которые вы указали, являются законными, потому что аргумент имеет четко определенный тип, поэтому аргумент шаблона T
может быть выведен просто отлично.
Ваш фрагмент с auto
также работает, потому что il
считается типом std::initializer_list<char>
, поэтому аргумент шаблона printme()
может быть выведен.
Единственная "забавная" часть здесь состоит в том, что auto
будет выбирать тип std::initializer_list<char>
, но аргумент шаблона не будет. Это связано с тем, что в § 14.8.2.5/5 стандарта С++ 11 явно указано, что это не выведенный контекст для аргумента шаблона:
Параметр функции, для которого связанный аргумент представляет собой список инициализаторов (8.5.4), но параметр не имеет std:: initializer_list или ссылки на возможный тип std:: initializer_list cv. [Пример:
template<class T> void g(T); g({1,2,3}); // error: no argument deduced for T
- конец примера]
Однако с auto
в § 7.1.6.4/6 имеется явная поддержка std::initializer_list<>
если инициализатор представляет собой скопированный-init-список (8.5.4), с
std::initializer_list<U>
.