#include <boost/type_index.hpp>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> initv { 42, 31, 7 };
std::vector v1{initv.begin(), initv.end()}; // CTAD
std::vector<int> v2{initv.begin(), initv.end()};
std::cout << boost::typeindex::type_id_with_cvr<decltype(v1)>().pretty_name() << std::endl;
std::cout << boost::typeindex::type_id_with_cvr<decltype(v2)>().pretty_name() << std::endl;
}
output:
std::vector<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, std::allocator<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > > > >
std::vector<int, std::allocator<int> >
CTAD produces a vector with iterators, not integers.
Is this correct, given that std::vector has a constructor that takes iterators ?
This is because of how you initialize the vector. With
You are doing direct-list-initialization which uses the
std::initializer_listconstructor and the list contains 2std::vector<int>::iterators. This is why it deduces for iterators.If you switch to using parentheses instead like
then you are no longer using the
std::initializer_listconstructor and instead using the iterator range constructor which will correctly deduce thevalue_typeof the iterators.To summerize, when you use
{}you are signaling you are using a list of initializers, so that is what is used if it is available.If you would like to take a deep dive down the rabbit hole that is initialization in C++, I strongly recommend watching Nicolai Josuttis CPPCON talk “The Nightmare of Initialization in C++”