Example
template<auto... Ns> consteval auto fn() {
std::vector v{Ns...};
return std::size(v);
}
static_assert(3uz == fn<1, 2, 3>());
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; }));
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()>{});
}
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()>{});
}