C++14(17) で zip 書いてみた

現状の C++ で zip を書いたらどうなるんだろう、と思って書いてみました。

[コード]

#include <iostream>
#include <algorithm>
#include <vector>
#include <tuple>

template<typename T, typename U>
constexpr auto
zip_impl(T v1, U v2){
    auto vi1 = std::begin(v1);
    auto vi2 = std::begin(v2);

    using value_t = decltype(std::make_tuple(*vi1, *vi2));
    std::vector<value_t> result{};

    while(vi1 != std::end(v1) && vi2 != std::end(v2)){
        result.emplace_back(*vi1, *vi2);
        vi1++;
        vi2++;
    }
    return result;
}

template<typename T, typename U>
constexpr auto
zip(T v1, U v2){
    return zip_impl(v1, v2);
}

template<typename T, typename U>
constexpr auto
zip(std::initializer_list<T> v1, std::initializer_list<U> v2){
    return zip_impl(v1, v2);
}


int
main(){
    for(auto [x, y] : zip({1, 2, 3, 4, 5}, {'a', 'b', 'c', 'd', 'e'})){
        std::cout << x << ":" << y << std::endl;
    }
    return 0;
}

[出力]

1:a
2:b
3:c
4:d
5:e

https://wandbox.org/permlink/qQEvmwNMjgVt3GHJ

手癖で constexpr をつけているけど特に constexpr ではない(std::vector に依存してるので constexpr には出来ない…。
使う側では C++17 の『構造化束縛』を使っているけど、実装側は C++14 でも動作すると思う。
っていうか、range based-for で構造化束縛使うのかなり強力なのではないだろうか???
実装は単純に2つのコンテナを iterator で回しながらタプルで保持するようにしてるだけですね。
特に複雑なことはしていないと思う。
最適解かどうかは別としてこういうコードが C++ でも雑に書けるようになったのはだいぶよさがあるなあ。