#pragma once // STL includes #include #include // std::forward, std::integer_sequence #include // std::tuple, std::get #include // std::initializer_list namespace cl { namespace util { namespace detail { // Borrowed from: // https://www.fluentcpp.com/2019/03/05/for_each_arg-applying-a-function-to-each-argument-of-a-function-in-cpp/ template F for_each_arg(F f, Args&&... args) { (void)std::initializer_list{ ( (void)f(std::forward(args)), 0)... }; return f; } namespace impl { // Borrowed from: https://stackoverflow.com/a/16387374/1476661 template void for_each_in_tuple(T&& t, F&& f, std::integer_sequence) { auto l = { (std::forward(f)(std::get(std::forward(t))), 0)... }; (void)l; } } template void for_each_in_tuple(std::tuple const& t, F&& f) { impl::for_each_in_tuple( t, std::forward(f), std::make_integer_sequence()); } namespace impl { // Borrowed from // https://codereview.stackexchange.com/questions/193420/apply-a-function-to-each-element-of-a-tuple-map-a-tuple template auto transform_tuple(Tuple&& t, F&& f, std::index_sequence) { return std::make_tuple(std::forward(f)(std::get(t))...); } } template auto transform_tuple(const std::tuple& t, F&& f) { return impl::transform_tuple( t, std::forward(f), std::make_index_sequence{}); } namespace impl { // Borrowed from // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html // with modifications of Casey Carter at // https://stackoverflow.com/a/51365112/1476661 template auto apply(F&& f, Tuple&& args, std::index_sequence) -> decltype(std::forward(f)( std::get(std::forward(args))...)) { return std::forward(f)( std::get(std::forward(args))...); } } template >::value>> auto apply(F&& f, Tuple&& args) -> decltype(impl::apply(std::forward(f), std::forward(args), Indices())) { return impl::apply(std::forward(f), std::forward(args), Indices()); } } } }