Braced-init-lists and function template type deduction order
c++, c++11, list-initialization, templates, type-deduction
Solution
Let's use an even simpler example:
template<class T>
void foo(T, T);
foo(42, {});
The function call has two arguments:
- a prvalue expression of type `int` (an integer literal)
- a braced-init-list `{}`
The latter, `{}`, can be part of an expression-list but it is not an expression itself. An expression-list is defined as an initializer-list. braced-init-lists do not have a type.
Template type deduction is done for each function parameter individually [temp.deduct.type]/2. [temp.deduct.call]/1 states about type deduction for a function parameter `P`:
If removing references and cv-qualifiers from `P` gives `std::initializer_list<`P'`>` for some P' and the argument is an initializer list, then deduction is performed instead for each element of the initializer list, taking P' as a function template parameter type and the initializer element as its argument. Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context. [emphasis mine]
So in the call `foo(42, {});` the `T` will not be deduced from the second argument `{}`. However, `T` can be deduced from the first argument.
In general, we can deduce `T` from multiple function parameters. In that case, the deduced types have to match exactly [temp.deduct.type]/2. There is no problem if the type is only deduced from one function parameter but used elsewhere (in another function parameter that is in a non-deduced context, in the return type etc). Type deduction can fail e.g. when a template parameter cannot be deduced from any function parameter and is not set explicitly.
After deduction, `T` will be substituted by `int`, producing a function signature similar to:
void foo<int>(int, int);
This function can be called with the two arguments `42` and `{}`. The latter will perform a copy-list-initialization leading to a value-initialization of the second parameter.
Problem
I have a question regarding the function template parameter type deduction procedure. Take this example: ``` #include <vector> #include <sstream> #include <string> #include <iterator> #include <fstream> int main() { std::ifstream file("path/to/file"); std::vector<int> vec(std::istream_iterator<int>{file},{}); // <- This part return 0; } ``` If I understand things correctly, the second parameter is deduced to be of type `std::istream_iterator` of which the default constructor is called. The appropriate `std::vector` constructor is declared as: ``` template <class InputIterator> vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()); ``` Since the first parameter type is deduced as `std::istream_iterator<int>` the second parameter is deduced as `std::istream_iterator<int>` too and so the uniform initialization semantics can be applied. What I have no idea about is at what order the type deduction happens. I would really appreciate some info on this. Thanks in advance!