Skip to content

Instantly share code, notes, and snippets.

@Fiona-J-W
Created March 1, 2019 22:51
Show Gist options
  • Save Fiona-J-W/33d10b3a7822050b2e55db332ff66cbf to your computer and use it in GitHub Desktop.
Save Fiona-J-W/33d10b3a7822050b2e55db332ff66cbf to your computer and use it in GitHub Desktop.
variadic distribute
/// CC-0 2019, Florian Weber
#include <cassert>
#include <cstdint>
#include <tuple>
#include <type_traits>
#include <utility>
namespace impl {
template <std::size_t Index, typename Value, typename... OutIt>
void output(std::size_t i, Value& value, std::tuple<OutIt&...>& outputs) {
if (i == Index) {
auto& output = std::get<Index>(outputs);
*output = std::move(value);
++output;
}
}
template <typename InputIt, typename InputEnd, typename F, typename... OutIt,
std::size_t... Indices>
void distribute(InputIt it, InputEnd last, F fun, std::tuple<OutIt&...> outputs,
std::index_sequence<Indices...>) {
for (; it != last; ++it) {
auto value = *it;
const auto index = fun(std::as_const(value));
assert(index < sizeof...(Indices));
std::initializer_list{(output<Indices>(index, value, outputs), 0)...};
}
}
} // namespace impl
template <typename InputIt, typename InputEnd, typename F, typename... OutIt>
void distribute(InputIt first, InputEnd last, F fun, OutIt... outputs) {
impl::distribute(first, last, fun, std::tie(outputs...),
std::make_index_sequence<sizeof...(OutIt)>{});
}
// And now for an example:
#include <iostream>
#include <iterator>
#include <vector>
int main() {
auto v0 = std::vector<int>{};
auto v1 = std::vector<int>{};
auto v2 = std::vector<int>{};
const auto fun = [](int i) { return static_cast<unsigned>(((i % 3) + 3) % 3); };
distribute(std::istream_iterator<int>{std::cin}, std::istream_iterator<int>{}, fun,
std::back_inserter(v0), std::back_inserter(v1), std::back_inserter(v2));
std::cout << "0 mod 3:\n";
std::copy(v0.begin(), v0.end(), std::ostream_iterator<int>{std::cout, ", "});
std::cout << "\n1 mod 3:\n";
std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>{std::cout, ", "});
std::cout << "\n2 mod 3:\n";
std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>{std::cout, ", "});
std::cout << '\n';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment