Skip to content

Instantly share code, notes, and snippets.

@dyigitpolat
Last active March 4, 2022 16:57
Show Gist options
  • Save dyigitpolat/0d99b5f6ae182fbcf0716f4c53ad5f02 to your computer and use it in GitHub Desktop.
Save dyigitpolat/0d99b5f6ae182fbcf0716f4c53ad5f02 to your computer and use it in GitHub Desktop.
pack projection with non-evaluated lambda
#include <tuple>
#include <variant>
#include <type_traits>
#include <utility>
template <
template <typename Q> typename MetaProj,
typename... Ts>
class PackProjector
{
using TP = std::tuple<MetaProj<Ts>...>;
template <std::size_t idx>
using get_type = typename std::tuple_element<idx, TP>::type;
template <
template <typename... Qs> typename MetaPred,
typename... Types>
struct Helper { using type = MetaPred<Types...>; };
public:
template <typename Q>
using projection = MetaProj<Q>;
template <template <typename... Qs> typename MetaPred>
using apply = decltype(
[]<std::size_t ...Idx> (std::index_sequence<Idx...>)
{
return Helper<MetaPred, get_type<Idx>... >{};
}(std::make_index_sequence<std::tuple_size<TP>{}>{}))::type;
};
///////////
// USAGE //
template <typename... Ts>
struct A
{
// simple projection
using PtrsProj = PackProjector<std::add_pointer_t, Ts...>;
using tuple_of_ts_ptr = typename PtrsProj::template apply<std::tuple>;
using variant_of_ts_ptr = typename PtrsProj::template apply<std::variant>;
// nested projection
template <typename T>
using NewProj1 = std::add_pointer_t<typename PtrsProj::projection<T>>;
using Ptrs2Proj = PackProjector<NewProj1, Ts...>;
template <typename T>
using NewProj2 = std::add_pointer_t<NewProj1<T>>;
using Ptrs3Proj = PackProjector<NewProj2, Ts...>;
template <typename T>
using NewProj3 = std::add_pointer_t<NewProj2<T>>;
using Ptrs4Proj = PackProjector<NewProj3, Ts...>;
using tuple_of_ts_ptr4 = typename Ptrs4Proj::template apply<std::tuple>;
using variant_of_ts_ptr4 = typename Ptrs4Proj::template apply<std::variant>;
};
// simple projection
static_assert(
std::is_same_v<
A<int, double>::tuple_of_ts_ptr,
std::tuple<int*, double*>>);
static_assert(
std::is_same_v<
A<int, double>::variant_of_ts_ptr,
std::variant<int*, double*>>);
// nested projection
static_assert(
std::is_same_v<
A<int, double>::tuple_of_ts_ptr4,
std::tuple<int****, double****>>);
static_assert(
std::is_same_v<
A<int, double>::variant_of_ts_ptr4,
std::variant<int****, double****>>);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment