#include <boost/type_index.hpp>
#include <iostream>
#include <vector>
int main()
{
std::vector v{2, 3.14};
std::cout << boost::typeindex::type_id_with_cvr<decltype(v)>().pretty_name() << '\n';
std::cout << "size: " << v.size() << '\n';
for (auto x : v)
std::cout << "- " << x << '\n';
}
The output is:
std::vector<double, std::allocator<double> >
size: 2
- 2
- 3.14
std::vector
instantiation uses auto-type-deduction (CTAD).
Apparently, the initializer_list
constructor is used (checked), but why does it accept both an int
and a double
and still deduces the type as vector<double>
?
If I increase the number of elements (while mixing int
and double
), compilation fails.
The same result with gcc
and clang
$ g++ --version
g++ (GCC) 13.0.1 20230401 (Red Hat 13.0.1-0)
$ clang++ --version
clang version 16.0.1 (Fedora 16.0.1-1.fc38)
There are two instances of overload resolution happening here. The first is to deduce the template argument. Since the two types in the init-list are different, the size+value constructor (or more formally, the deduction guide generated from said constructor) is picked here, deducing the type to be double
.
Then overload resolution runs again to create the object. With the type now known as double
, the list constructor is now valid, and thus used to initialize the object.