There are several ways to construct a std::vector
. One of them is by passing 2 input iterators on it:
template <class InputIt >constexpr vector (InputIt first, InputIt last, const Allocator &alloc = Allocator()) ;
enum class tokenType { };std::map<std::string, tokenType> keywords { {"else" , tokenType::ELSE}, {"if" , tokenType::IF}, }; std::vector<std::pair<std::string, tokenType>> kv (keywords.begin (), keywords.end ());
CTAD allows us to drop type parameters with C++17 and onward:
std::vector kv (keywords.begin(), keywords.end()) ;
Another use case is reading from a file:
$ more weather-forecast.dat 29.0078352897646 38.3680151369284 25.7318773688196 30.7462548296841 ...
We can directly read it into the vector with istream_iterator
s:
std::ifstream fin{"weather-forecast.dat" }; std::istream_iterator<double > begin{fin}; std::istream_iterator<double > end{}; std::vector<double > weatherStats (begin, end) ;auto average = std::accumulate (weatherStats.begin (), weatherStats.end (), double (0 )) / weatherStats.size ();
The default initialized istream_iterator
will behave like the end iterator, so we can define it in place:
std::vector<double > weatherStats (std::istream_iterator<double >{fin}, {}) ;auto average = std::accumulate (begin (weatherStats), end (weatherStats), double (0 )) / size (weatherStats);
and this is a pattern. To read from a file string by string:
std::vector<std::string> words (std::istream_iterator<std::string>{fin}, {}) ;
or you’re writing an interpreter and need to store the source file, istream_iterator
will skip the white space. noskipws
flag can alter this behaviour:
std::vector<char > source (std::istream_iterator<char >{fin >> std::noskipws}, {}) ;
or you’re writing an emulator and need to keep the game binary. istreambuf_iterator
can be used:
std::vector<char > rom (std::istreambuf_iterator<char >{fin}, {}) ;
maybe you need to delay the construction, iterator overload of the assign()
member will work:
template <class InputIt >constexpr void assign (InputIt first, InputIt last) ;
class cartridge { std::vector<char > m_data; public : void plug (std::filesystem::path p) { std::fstream fin{p}; m_data.assign (std::istreambuf_iterator<char >{fin}, {}); } };
Built-in arrays are decay into pointers and can be used as an iterator:
int fibo[] = {0 , 1 , 1 , 2 , 3 , 5 };std::vector<int > fibo_vec (fibo, fibo + std::size(fibo)) ;
Using nonmember std::begin()
and std::end()
will be better option in this case, but still, we may need it:
std::vector<std::string_view> args (argv, argv + argc) ;
std::vector
has 5 other (excluding copy and move special members) constructors which each waiting to be discovered :) Thanks for reading.