You really shouldn't be trying to translate idioms directly from one language to another.
In C++, you generally don't write functions that take iterators and generate new iterators; instead, you write functions that take input and output iterators and copy from one to the other. So, you could write a zip
function that take an input iterator over T
, an input iterator over U
, and an output iterator over pair<T, U>
.
But then you're not going to chain the two calls together this way, because your zip
function isn't going to be returning anything (like an iterator range) that could be usefully passed to any kind of dict
function. Instead, you might create a dict
analog (an unordered_map
), create an output iterator into that, and use a zip
function to copy pairs into it.
Something like this:
template <I1, I2, O>
void zip(I1 it1, I1 it1end, I2 it2, I2 it2end, O o) {
while ((it1 != it1end) && (it2 != it2end)) {
*o++ = std::make_pair(*it1++, *it2++);
}
}
std::unordered_map<T, U> mapping;
zip(c1.begin(), c1.end(), c2.begin(), c2.end(), std::inserter(mapping, mapping.end()));
Except I don't think you can actually use inserter
on an unordered_map
this way or not, so you've have to write a map_inserter
function instead.
If you don't know the types T
and U
locally, you may want to wrap this all up in a function template that extracts the types from the element types of the iterators so you can auto
it. (In C++11, you can decltype
it without needing a function, but the expression will be a mess.)
If you have multiple uses for zip
and map_inserter
, it may be worth writing them. But otherwise, a better solution would be to expand it into an explicit loop:
auto it1 = c1.begin(), it1end = c1.end(), it2 = c2.begin(), it2end = c2.end();
std::unordered_map<T, U> mapping;
while ((it1 != it1end) && (it2 != it2end)) {
mapping[*it1++] = *it2++;
}