#include <iostream> // for std::cout
#include <iterator> // for std::ostream_iterator
#include <tuple> // for std::tie
#include <type_traits> // for std::enable_if
#include <vector> // for std::vector
template<typename T>
struct identity { using type = T; };
template<typename Integral, Integral... N>
struct integer_sequence {
template<Integral Offset>
struct offset : identity<integer_sequence<Integral, (N + Offset)...>> { };
};
namespace detail {
template<typename... T>
void ignore(T&&...) { }
template<std::size_t Idx, typename... T>
inline auto nth_arg(T&&... arg)
-> decltype(std::get<Idx>(std::tie(arg...))) {
return std::get<Idx>(std::tie(arg...));
}
template<std::size_t N, std::size_t... T>
struct gen_iter_indices
: gen_iter_indices<(N - 2), (N - 2), T...> { };
template<std::size_t... T>
struct gen_iter_indices<0, T...>
: identity<integer_sequence<std::size_t, T...>> { };
template<
typename... Iterator,
typename Integral,
Integral... Begin,
Integral... End
>
inline static bool eq_n(const std::tuple<Iterator...>& iters,
integer_sequence<Integral, Begin...>,
integer_sequence<Integral, End...>)
{
const bool res[] { (std::get<Begin>(iters) == std::get<End>(iters))... };
for(std::size_t i = 0; i < sizeof...(Begin); ++i) {
if(res[i]) { return true; }
}
return false;
}
template<typename... Iterator, typename Integral, Integral... Begin>
inline static void increment_n(const std::tuple<Iterator...>& iters,
integer_sequence<Integral, Begin...>)
{
ignore(++std::get<Begin>(iters)...);
}
template<
typename NaryOperation,
typename... Iterator,
typename Integral,
Integral... Begin
>
inline auto call_n(const std::tuple<Iterator...>& iters,
NaryOperation op,
integer_sequence<Integral, Begin...>)
-> decltype(op(*std::get<Begin>(iters)...))
{
return op(*std::get<Begin>(iters)...);
}
}
template<
typename OutputIter,
typename NaryOperation,
typename... InputIter,
typename = typename std::enable_if<
(2 <= sizeof...(InputIter)) && // Atleast one iterator pair
(0 == (sizeof...(InputIter) % 2)) // and multiple of two
>::type
>
static OutputIter transform_n(OutputIter out_iter,
NaryOperation op,
InputIter... in_iter)
{
using begins = typename detail::gen_iter_indices<sizeof...(InputIter)>::type;
using ends = typename begins::template offset<1>::type;
const auto iters = std::tie(in_iter...); // tuple of references to iterators
while(!detail::eq_n(iters, begins{}, ends{})) {
*out_iter = detail::call_n(iters, op, begins{});
++out_iter;
detail::increment_n(iters, begins{});
}
return out_iter;
}
int main(int argc, char** argv) {
std::vector<int> v1 { 1, 2, 3 };
std::vector<int> v2 { 4, 5, 6 };
std::vector<int> v3 { 7, 8, 9 };
std::vector<int> res { };
res.resize(3);
auto end = transform_n(
res.begin(),
[](int _1, int _2, int _3) { return _1 + _2 + _3; },
v1.begin(),
v1.end(),
v2.begin(),
v2.end(),
v3.begin(),
v3.end()
);
std::copy(res.begin(), end, std::ostream_iterator<int>(std::cout, " "));
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPiAgICAgLy8gZm9yIHN0ZDo6Y291dAojaW5jbHVkZSA8aXRlcmF0b3I+ICAgICAvLyBmb3Igc3RkOjpvc3RyZWFtX2l0ZXJhdG9yCiNpbmNsdWRlIDx0dXBsZT4gICAgICAgIC8vIGZvciBzdGQ6OnRpZQojaW5jbHVkZSA8dHlwZV90cmFpdHM+ICAvLyBmb3Igc3RkOjplbmFibGVfaWYKI2luY2x1ZGUgPHZlY3Rvcj4gICAgICAgLy8gZm9yIHN0ZDo6dmVjdG9yCgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzdHJ1Y3QgaWRlbnRpdHkgeyB1c2luZyB0eXBlID0gVDsgfTsKCnRlbXBsYXRlPHR5cGVuYW1lIEludGVncmFsLCBJbnRlZ3JhbC4uLiBOPgpzdHJ1Y3QgaW50ZWdlcl9zZXF1ZW5jZSB7CgogIHRlbXBsYXRlPEludGVncmFsIE9mZnNldD4KICBzdHJ1Y3Qgb2Zmc2V0IDogaWRlbnRpdHk8aW50ZWdlcl9zZXF1ZW5jZTxJbnRlZ3JhbCwgKE4gKyBPZmZzZXQpLi4uPj4geyB9Owp9OwoKbmFtZXNwYWNlIGRldGFpbCB7CgogIHRlbXBsYXRlPHR5cGVuYW1lLi4uIFQ+CiAgdm9pZCBpZ25vcmUoVCYmLi4uKSB7IH0KCiAgdGVtcGxhdGU8c3RkOjpzaXplX3QgSWR4LCB0eXBlbmFtZS4uLiBUPgogIGlubGluZSBhdXRvIG50aF9hcmcoVCYmLi4uIGFyZykKICAtPiBkZWNsdHlwZShzdGQ6OmdldDxJZHg+KHN0ZDo6dGllKGFyZy4uLikpKSB7CiAgICByZXR1cm4gc3RkOjpnZXQ8SWR4PihzdGQ6OnRpZShhcmcuLi4pKTsKICB9CgogIHRlbXBsYXRlPHN0ZDo6c2l6ZV90IE4sIHN0ZDo6c2l6ZV90Li4uIFQ+CiAgc3RydWN0IGdlbl9pdGVyX2luZGljZXMKICA6IGdlbl9pdGVyX2luZGljZXM8KE4gLSAyKSwgKE4gLSAyKSwgVC4uLj4geyB9OwogIHRlbXBsYXRlPHN0ZDo6c2l6ZV90Li4uIFQ+CiAgc3RydWN0IGdlbl9pdGVyX2luZGljZXM8MCwgVC4uLj4KICA6IGlkZW50aXR5PGludGVnZXJfc2VxdWVuY2U8c3RkOjpzaXplX3QsIFQuLi4+PiB7IH07CgogIHRlbXBsYXRlPAogICAgdHlwZW5hbWUuLi4gSXRlcmF0b3IsCiAgICB0eXBlbmFtZSBJbnRlZ3JhbCwKICAgIEludGVncmFsLi4uIEJlZ2luLAogICAgSW50ZWdyYWwuLi4gRW5kCiAgPgogIGlubGluZSBzdGF0aWMgYm9vbCBlcV9uKGNvbnN0IHN0ZDo6dHVwbGU8SXRlcmF0b3IuLi4+JiBpdGVycywKICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlZ2VyX3NlcXVlbmNlPEludGVncmFsLCBCZWdpbi4uLj4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZWdlcl9zZXF1ZW5jZTxJbnRlZ3JhbCwgRW5kLi4uPikKICB7CiAgICBjb25zdCBib29sIHJlc1tdIHsgKHN0ZDo6Z2V0PEJlZ2luPihpdGVycykgPT0gc3RkOjpnZXQ8RW5kPihpdGVycykpLi4uIH07CiAgICBmb3Ioc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBzaXplb2YuLi4oQmVnaW4pOyArK2kpIHsKICAgICAgaWYocmVzW2ldKSB7IHJldHVybiB0cnVlOyB9CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQoKICB0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBJdGVyYXRvciwgdHlwZW5hbWUgSW50ZWdyYWwsIEludGVncmFsLi4uIEJlZ2luPgogIGlubGluZSBzdGF0aWMgdm9pZCBpbmNyZW1lbnRfbihjb25zdCBzdGQ6OnR1cGxlPEl0ZXJhdG9yLi4uPiYgaXRlcnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVnZXJfc2VxdWVuY2U8SW50ZWdyYWwsIEJlZ2luLi4uPikKICB7CiAgICBpZ25vcmUoKytzdGQ6OmdldDxCZWdpbj4oaXRlcnMpLi4uKTsKICB9CgogIHRlbXBsYXRlPAogICAgdHlwZW5hbWUgTmFyeU9wZXJhdGlvbiwKICAgIHR5cGVuYW1lLi4uIEl0ZXJhdG9yLAogICAgdHlwZW5hbWUgSW50ZWdyYWwsCiAgICBJbnRlZ3JhbC4uLiBCZWdpbgogID4KICBpbmxpbmUgYXV0byBjYWxsX24oY29uc3Qgc3RkOjp0dXBsZTxJdGVyYXRvci4uLj4mIGl0ZXJzLAogICAgICAgICAgICAgICAgICAgICBOYXJ5T3BlcmF0aW9uIG9wLAogICAgICAgICAgICAgICAgICAgICBpbnRlZ2VyX3NlcXVlbmNlPEludGVncmFsLCBCZWdpbi4uLj4pCiAgLT4gZGVjbHR5cGUob3AoKnN0ZDo6Z2V0PEJlZ2luPihpdGVycykuLi4pKQogIHsKICAgIHJldHVybiBvcCgqc3RkOjpnZXQ8QmVnaW4+KGl0ZXJzKS4uLik7CiAgfQp9Cgp0ZW1wbGF0ZTwKICB0eXBlbmFtZSBPdXRwdXRJdGVyLAogIHR5cGVuYW1lIE5hcnlPcGVyYXRpb24sCiAgdHlwZW5hbWUuLi4gSW5wdXRJdGVyLAogIHR5cGVuYW1lID0gIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPAogICAgICAgICAgICAgICAgKDIgPD0gc2l6ZW9mLi4uKElucHV0SXRlcikpICYmICAgIC8vIEF0bGVhc3Qgb25lIGl0ZXJhdG9yIHBhaXIKICAgICAgICAgICAgICAgICgwID09IChzaXplb2YuLi4oSW5wdXRJdGVyKSAlIDIpKSAvLyBhbmQgbXVsdGlwbGUgb2YgdHdvCiAgICAgICAgICAgICAgPjo6dHlwZQo+CnN0YXRpYyBPdXRwdXRJdGVyIHRyYW5zZm9ybV9uKE91dHB1dEl0ZXIgb3V0X2l0ZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5hcnlPcGVyYXRpb24gb3AsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElucHV0SXRlci4uLiBpbl9pdGVyKQp7CiAgdXNpbmcgYmVnaW5zID0gdHlwZW5hbWUgZGV0YWlsOjpnZW5faXRlcl9pbmRpY2VzPHNpemVvZi4uLihJbnB1dEl0ZXIpPjo6dHlwZTsKICB1c2luZyBlbmRzID0gdHlwZW5hbWUgYmVnaW5zOjp0ZW1wbGF0ZSBvZmZzZXQ8MT46OnR5cGU7CgogIGNvbnN0IGF1dG8gaXRlcnMgPSBzdGQ6OnRpZShpbl9pdGVyLi4uKTsgLy8gdHVwbGUgb2YgcmVmZXJlbmNlcyB0byBpdGVyYXRvcnMKCiAgd2hpbGUoIWRldGFpbDo6ZXFfbihpdGVycywgYmVnaW5ze30sIGVuZHN7fSkpIHsKICAgICpvdXRfaXRlciA9IGRldGFpbDo6Y2FsbF9uKGl0ZXJzLCBvcCwgYmVnaW5ze30pOwogICAgKytvdXRfaXRlcjsKICAgIGRldGFpbDo6aW5jcmVtZW50X24oaXRlcnMsIGJlZ2luc3t9KTsKICB9CgogIHJldHVybiBvdXRfaXRlcjsKfQoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIqKiBhcmd2KSB7CiAgc3RkOjp2ZWN0b3I8aW50PiB2MSB7IDEsIDIsIDMgfTsKICBzdGQ6OnZlY3RvcjxpbnQ+IHYyIHsgNCwgNSwgNiB9OwogIHN0ZDo6dmVjdG9yPGludD4gdjMgeyA3LCA4LCA5IH07CiAgc3RkOjp2ZWN0b3I8aW50PiByZXMgeyB9OwogIHJlcy5yZXNpemUoMyk7CiAgYXV0byBlbmQgPSB0cmFuc2Zvcm1fbigKICAgIHJlcy5iZWdpbigpLAogICAgW10oaW50IF8xLCBpbnQgXzIsIGludCBfMykgeyByZXR1cm4gXzEgKyBfMiArIF8zOyB9LAogICAgdjEuYmVnaW4oKSwKICAgIHYxLmVuZCgpLAogICAgdjIuYmVnaW4oKSwKICAgIHYyLmVuZCgpLAogICAgdjMuYmVnaW4oKSwKICAgIHYzLmVuZCgpCiAgKTsKICBzdGQ6OmNvcHkocmVzLmJlZ2luKCksIGVuZCwgc3RkOjpvc3RyZWFtX2l0ZXJhdG9yPGludD4oc3RkOjpjb3V0LCAiICIpKTsKICByZXR1cm4gMDsKfQ==