我建议简化函数的签名,而不是对vectors 或std::function 进行硬编码。
由于您已经定义了一个函数模板,您不妨接受任何范围和任何可调用对象:
Live On Compiler Explorer
template <typename F, typename... Rs>
auto zip(F f, Rs const&... args) {
using R = std::decay_t<
std::invoke_result_t<F, typename Rs::value_type...>
>;
auto const n = std::min({args.size()...});
std::vector<R> r(n);
for (size_t i = 0; i<n; ++i)
r[i] = f(args[i]...);
return r;
}
其实,当你泛化的时候,你最终会得到 RangeV3 的zip_with:
template <typename F, typename... Rs>
auto my_zip(F&& f, Rs const&... args) {
return r::to_vector(v::zip_with(f, args...));
}
我认为默认情况下你可以不用to_vector。
Live On Compiler Explorer
#include <fmt/ranges.h>
#include <functional>
#include <iostream>
#include <map>
#include <range/v3/all.hpp>
#include <vector>
namespace r = ::ranges;
namespace v = r::views;
using namespace std::string_literals;
template <typename F, typename... Rs>
auto zip(F f, Rs const&... args) {
return v::zip_with(std::move(f), args...);
}
template <typename F, typename... Rs>
auto zip_vec(F const& f, Rs const&... args) {
return r::to_vector(zip(f, args...));
}
auto foo(int x, std::string_view s) {
std::string r(s.size() * x, '\0');
while (x--) {
std::copy(s.begin(), s.end(), r.begin() + x * s.size());
}
return r;
}
int main() {
std::vector<int> a{ 1, 3 }, b{ 2, -2 };
auto mul = std::multiplies<>{};
fmt::print("{} x {} -> {}\n", a, b, zip(mul, a, b));
auto ret = zip_vec(std::plus<>{}, a, b);
fmt::print("ret as a vector: {}\n", ret);
static_assert(std::is_same_v<decltype(ret), std::vector<int>>);
std::map<std::string, int> m { {"one"s, 1}, {"three"s, 3} };
fmt::print("But also using a non-vectors: {}\nor {}\n",
zip(foo, a, m | v::keys),
zip(mul, a, m | v::values));
}
打印
{1, 3} x {2, -2} -> {2, -6}
ret as a vector: {3, 1}
But also using a non-vectors: {"one", "threethreethree"}
or {1, 9}