#include <vector>
#include <string>
#include <iostream>
#include <list>
using namespace std;
template<class InputIt1, class InputIt2, class BinaryFunction>
BinaryFunction for_each_impl(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryFunction f, std::random_access_iterator_tag, std::random_access_iterator_tag)
{
std::cout << "Optimized for random access.\n";
if (last1 - first1 < last2 - first2)
{
for (; first1 != last1; ++first1, ++first2) {
f(*first1, *first2);
}
}
else
{
for (; first2 != last2; ++first1, ++first2) {
f(*first1, *first2);
}
}
return f;
}
template<class InputIt1, class InputIt2, class BinaryFunction>
BinaryFunction for_each_impl(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryFunction f, std::input_iterator_tag, std::input_iterator_tag)
{
std::cout << "Generic implementation.\n";
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
f(*first1, *first2);
}
return f;
}
template<class InputIt1, class InputIt2, class BinaryFunction>
BinaryFunction for_each(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryFunction f)
{
typedef typename std::iterator_traits<InputIt1>::iterator_category Category1;
typedef typename std::iterator_traits<InputIt2>::iterator_category Category2;
return for_each_impl(first1, last1, first2, last2, f, Category1(), Category2());
}
template <template <typename, typename> class ContainerT>
void test()
{
ContainerT<int, std::allocator<int>> example;
example.push_back(42);
example.push_back(1729);
ContainerT<string, std::allocator<string>> example2;
example2.push_back("forty two");
example2.push_back("seventeen twenty nine");
for_each(example.cbegin(), example.cend(), example2.cbegin(), example2.cend(),
[](int left, string const& right) { std::cout << left << " is " << right << "\n"; });
}
int main() {
test<list>();
test<vector>();
}
I2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bGlzdD4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnRlbXBsYXRlPGNsYXNzIElucHV0SXQxLCBjbGFzcyBJbnB1dEl0MiwgY2xhc3MgQmluYXJ5RnVuY3Rpb24+CkJpbmFyeUZ1bmN0aW9uIGZvcl9lYWNoX2ltcGwoSW5wdXRJdDEgZmlyc3QxLCBJbnB1dEl0MSBsYXN0MSwgSW5wdXRJdDIgZmlyc3QyLCBJbnB1dEl0MiBsYXN0MiwgQmluYXJ5RnVuY3Rpb24gZiwgc3RkOjpyYW5kb21fYWNjZXNzX2l0ZXJhdG9yX3RhZywgc3RkOjpyYW5kb21fYWNjZXNzX2l0ZXJhdG9yX3RhZykKewoJc3RkOjpjb3V0IDw8ICJPcHRpbWl6ZWQgZm9yIHJhbmRvbSBhY2Nlc3MuXG4iOwogICAgaWYgKGxhc3QxIC0gZmlyc3QxIDwgbGFzdDIgLSBmaXJzdDIpCiAgICB7CiAgICAgICAgZm9yICg7IGZpcnN0MSAhPSBsYXN0MTsgKytmaXJzdDEsICsrZmlyc3QyKSB7CiAgICAgICAgICAgIGYoKmZpcnN0MSwgKmZpcnN0Mik7CiAgICAgICAgfQogICAgfQogICAgZWxzZQogICAgewogICAgICAgIGZvciAoOyBmaXJzdDIgIT0gbGFzdDI7ICsrZmlyc3QxLCArK2ZpcnN0MikgewogICAgICAgICAgICBmKCpmaXJzdDEsICpmaXJzdDIpOwogICAgICAgIH0KICAgIH0KICAgIAogICAgcmV0dXJuIGY7Cn0KCnRlbXBsYXRlPGNsYXNzIElucHV0SXQxLCBjbGFzcyBJbnB1dEl0MiwgY2xhc3MgQmluYXJ5RnVuY3Rpb24+CkJpbmFyeUZ1bmN0aW9uIGZvcl9lYWNoX2ltcGwoSW5wdXRJdDEgZmlyc3QxLCBJbnB1dEl0MSBsYXN0MSwgSW5wdXRJdDIgZmlyc3QyLCBJbnB1dEl0MiBsYXN0MiwgQmluYXJ5RnVuY3Rpb24gZiwgc3RkOjppbnB1dF9pdGVyYXRvcl90YWcsIHN0ZDo6aW5wdXRfaXRlcmF0b3JfdGFnKQp7CglzdGQ6OmNvdXQgPDwgIkdlbmVyaWMgaW1wbGVtZW50YXRpb24uXG4iOwogICAgZm9yICg7IGZpcnN0MSAhPSBsYXN0MSAmJiBmaXJzdDIgIT0gbGFzdDI7ICsrZmlyc3QxLCArK2ZpcnN0MikgewogICAgICAgIGYoKmZpcnN0MSwgKmZpcnN0Mik7CiAgICB9CiAgICByZXR1cm4gZjsKfQoKdGVtcGxhdGU8Y2xhc3MgSW5wdXRJdDEsIGNsYXNzIElucHV0SXQyLCBjbGFzcyBCaW5hcnlGdW5jdGlvbj4KQmluYXJ5RnVuY3Rpb24gZm9yX2VhY2goSW5wdXRJdDEgZmlyc3QxLCBJbnB1dEl0MSBsYXN0MSwgSW5wdXRJdDIgZmlyc3QyLCBJbnB1dEl0MiBsYXN0MiwgQmluYXJ5RnVuY3Rpb24gZikKewogICAgdHlwZWRlZiB0eXBlbmFtZSBzdGQ6Oml0ZXJhdG9yX3RyYWl0czxJbnB1dEl0MT46Oml0ZXJhdG9yX2NhdGVnb3J5IENhdGVnb3J5MTsKICAgIHR5cGVkZWYgdHlwZW5hbWUgc3RkOjppdGVyYXRvcl90cmFpdHM8SW5wdXRJdDI+OjppdGVyYXRvcl9jYXRlZ29yeSBDYXRlZ29yeTI7CiAgICByZXR1cm4gZm9yX2VhY2hfaW1wbChmaXJzdDEsIGxhc3QxLCBmaXJzdDIsIGxhc3QyLCBmLCBDYXRlZ29yeTEoKSwgQ2F0ZWdvcnkyKCkpOwp9Cgp0ZW1wbGF0ZSA8dGVtcGxhdGUgPHR5cGVuYW1lLCB0eXBlbmFtZT4gY2xhc3MgQ29udGFpbmVyVD4Kdm9pZCB0ZXN0KCkKewoJQ29udGFpbmVyVDxpbnQsIHN0ZDo6YWxsb2NhdG9yPGludD4+IGV4YW1wbGU7CglleGFtcGxlLnB1c2hfYmFjayg0Mik7CglleGFtcGxlLnB1c2hfYmFjaygxNzI5KTsKCUNvbnRhaW5lclQ8c3RyaW5nLCBzdGQ6OmFsbG9jYXRvcjxzdHJpbmc+PiBleGFtcGxlMjsKCWV4YW1wbGUyLnB1c2hfYmFjaygiZm9ydHkgdHdvIik7CglleGFtcGxlMi5wdXNoX2JhY2soInNldmVudGVlbiB0d2VudHkgbmluZSIpOwoJZm9yX2VhY2goZXhhbXBsZS5jYmVnaW4oKSwgZXhhbXBsZS5jZW5kKCksIGV4YW1wbGUyLmNiZWdpbigpLCBleGFtcGxlMi5jZW5kKCksCgkgICAgW10oaW50IGxlZnQsIHN0cmluZyBjb25zdCYgcmlnaHQpIHsgc3RkOjpjb3V0IDw8IGxlZnQgPDwgIiBpcyAiIDw8IHJpZ2h0IDw8ICJcbiI7IH0pOwp9CgppbnQgbWFpbigpIHsKCXRlc3Q8bGlzdD4oKTsKCXRlc3Q8dmVjdG9yPigpOwp9