Consider this simple generalization of std :: transform that I wrote for N input iterators:
#include <iostream>
#include <vector>
#include <string>
template <typename InputIterator, typename OutputIterator, typename NaryOperator, typename... InputIterators>
OutputIterator transform (InputIterator first, InputIterator last, OutputIterator result,
NaryOperator op, InputIterators... iterators) {
while (first != last) {
*result = op(*first, *iterators++...);
++result; ++first;
}
return result;
}
int main() {
const std::vector<int> a = {1,2,3,4,5};
const std::vector<double> b = {1.2, 4.5, 0.6, 2.8, 3.1};
const std::vector<std::string> c = {"hi", "howdy", "hello", "bye", "farewell"};
std::vector<double> result(5);
transform (a.begin(), a.end(), result.begin(),
[](int i, double d, const std::string& s)->double {return i + d + s.length();},
b.begin(), c.begin());
for (double x : result) std::cout << x << ' ';
}
Now I want to vectors a, b, chave different lengths (and the argument InputIterator lastcan be removed), and in this case transformwill continue to convert until the longest vector is used, using default values for shorter vectors.
, transform, transform , . transform, , ? :
transform (OutputIterator result, NaryOperator op, InputIterators... iterators);
: , - :
template <typename OutputIterator, typename NaryOperator, typename... InputIterators>
OutputIterator transform (OutputIterator result, NaryOperator op, InputIterators... first, InputIterators... last) {
while (true) {
*result = op((first == last ?
typename std::iterator_traits<InputIterators>::value_type() : *first++)...);
++result;
}
return result;
}
transform (result.begin(),
[](int i, double d, const std::string& s)->double {return i + d + s.length();},
a.begin(), b.begin(), c.begin(), a.end(), b.end(), c.end());
. , , last....
, :
template <typename OutputIterator, typename NaryOperator, typename... InputIteratorsPairs>
OutputIterator transform (OutputIterator result, NaryOperator op, InputIteratorsPairs... pairs) {
while (true) {
*result = op((pairs.first == pairs.second ?
typename InputIteratorsPairs::first_type() : *pairs.first++)...);
++result;
}
return result;
}
transform_ (result.begin(),
[](int i, double d, const std::string& s)->double {return i + d + s.length();},
std::make_pair(a.begin(), a.end()), std::make_pair(b.begin(), b.end()), std::make_pair(c.begin(), c.end()));
( ).