std::vector's iterator ctor

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()); // 5
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_iterators:

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}, {}); // {"to", "be", "or" .. }

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}, {});  // {'u', '8', ' ', '=', ' ', '3', '\n'}

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); // 2
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.