Skip to content

Latest commit

 

History

History
114 lines (93 loc) · 3.05 KB

309.md

File metadata and controls

114 lines (93 loc) · 3.05 KB
Info

Example

template<auto... Ns> consteval auto fn() {
  std::vector v{Ns...};
  return std::size(v);
}

static_assert(3uz == fn<1, 2, 3>());

https://godbolt.org/z/vx6cPaY8s

Puzzle

Can you simplify filter example by applying best C++ practicies?

#include <tuple>
#include <array>
#include <utility>
#include <vector>

constexpr auto filter(auto t, auto fn) {
    // get the size of filtered elements
    constexpr auto size = [=] {
        std::vector<std::size_t> v{};
        std::apply([&, i = 0](auto... ts) mutable {
            ([&] {
                if (fn(ts)) {
                    v.push_back(i);
                }
                i++;
            }(), ...);
        }, t());
        return v.size();
    }();

    // get the array of indecies of filtered elements
    constexpr auto values = [=] {
        std::array<std::size_t, size> values{};
        std::apply([&, x = 0, i = 0](auto... ts) mutable {
            ([&] {
                if (fn(ts)) {
                    values[x++] = i;
                }
                i++;
            }(), ...);
        }, t());
        return values;
    }();

    // convert array indicies to tuple elements
    return [=]<auto... Ns>(std::index_sequence<Ns...>) {
        return std::tuple{std::get<values[Ns]>(t())...};
    }(std::make_index_sequence<size>{});
};

static_assert(std::tuple{1, 2, 3} == filter([] { return std::tuple{1, 2, 3}; }, [](auto) { return true; }));
static_assert(std::tuple{} == filter([] { return std::tuple{1, 2, 3}; }, [](auto) { return false; }));
static_assert(std::tuple{1, 3} == filter([] { return std::tuple{1, 2, 3}; }, [](auto v) { return v != 2; }));
static_assert(std::tuple{2} == filter([] { return std::tuple{1, 2, 3}; }, [](auto v) { return v == 2; }));

https://godbolt.org/z/E7rTGdn7b

Solutions

constexpr auto filter(auto t, auto fn) {
  // get the vector of filtered elements
  constexpr auto r = [=] {
    return std::apply(
        [=](auto... ts) {
          return [=] {
            auto v = std::vector{ts...};
            std::erase_if(v, std::not_fn(fn));
            return v;
          };
        },
        t());
  }();

  // convert the vector to a tuple
  return [=]<auto... Ns>(std::index_sequence<Ns...>) {
    const auto v = r();
    return std::tuple{v[Ns]...};
  }(std::make_index_sequence<r().size()>{});
}

https://godbolt.org/z/WTMEPs93o

constexpr auto filter(auto t, auto fn) {
  constexpr auto v = std::apply(
      [=](auto... ts) {
        auto const ints = {ts...};
        return [=] () { return ints | std::views::filter(fn) | std::ranges::to<std::vector>(); };
      }, t());

  return [=]<auto... Ns>(std::index_sequence<Ns...>) {
    return std::tuple{v()[Ns]...};
  }(std::make_index_sequence<v().size()>{});
}

https://godbolt.org/z/3z3s4s6h6