Skip to content

Commit

Permalink
luple: lambda tuple
Browse files Browse the repository at this point in the history
  • Loading branch information
deepgrace committed Jun 4, 2024
1 parent 80bae99 commit 06b65e0
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 1 deletion.
19 changes: 19 additions & 0 deletions Tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,25 @@ int main(int argc, char* argv[])

zipped_tuple_map(f_, a_, b_);

luple l0;
luple l1(std::string("C++23"));

luple<short, char> l2;

auto l3 = make_luple(j, std::string("template"));
auto l4 = luple_cat(l0, l1, l2, l3);

using ltype = decltype(l4);

std::cout << l4.get<0>() << std::endl;
l4.apply([](std::string, short, char, double, std::string){});

is_identical<is_luple_v<ltype>>();
is_identical<luple_size_v<ltype>, 5>();

is_identical<luple_element_t<0, ltype>, std::string>();
is_identical<luple_element_t<3, ltype>, double>();

is_identical<triangular_number_v<4>, 10>();
is_identical<triangular_number_sequence_t<4>, std::integer_sequence<int, 1, 3, 6, 10>>();

Expand Down
19 changes: 19 additions & 0 deletions example/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,25 @@ int main(int argc, char* argv[])

zipped_tuple_map(f_, a_, b_);

luple l0;
luple l1(std::string("C++23"));

luple<short, char> l2;

auto l3 = make_luple(j, std::string("template"));
auto l4 = luple_cat(l0, l1, l2, l3);

using ltype = decltype(l4);

std::cout << l4.get<0>() << std::endl;
l4.apply([](std::string, short, char, double, std::string){});

is_identical<is_luple_v<ltype>>();
is_identical<luple_size_v<ltype>, 5>();

is_identical<luple_element_t<0, ltype>, std::string>();
is_identical<luple_element_t<3, ltype>, double>();

is_identical<triangular_number_v<4>, 10>();
is_identical<triangular_number_sequence_t<4>, std::integer_sequence<int, 1, 3, 6, 10>>();

Expand Down
196 changes: 196 additions & 0 deletions include/monster.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7374,6 +7374,202 @@ namespace monster
}
}

template <typename... Args>
class luple
{
public:
constexpr luple()
{
lambda([](storage<Args>&... s)
{
(..., s.init());
});
}

template <typename... Brgs, decltype((..., new(nullptr) Args(std::declval<Brgs>()))) = nullptr>
constexpr luple(Brgs&&... brgs)
{
lambda([&](storage<Args>&... s)
{
(..., s.init(std::forward<Brgs>(brgs)));
});
}

constexpr luple(const luple& l)
{
lambda([&](storage<Args>&... s)
{
l.lambda([&](const storage<Args>&... t)
{
(..., new (s.operator->()) Args(*t));
});
});
}

constexpr luple(luple&& l)
{
lambda([&](storage<Args>&... s)
{
l.lambda([&](storage<Args>&... t)
{
(..., new (s.operator->()) Args(static_cast<Args&&>(*t)));
});
});
}

template <typename F>
constexpr decltype(auto) apply(F&& f)
{
lambda([&](const storage<Args>&... s) -> decltype(auto)
{
return std::invoke(std::forward<F>(f), *s...);
});
}

template <size_t N>
constexpr decltype(auto) get()
{
return [&]<auto... n>(std::index_sequence<n...>)
{
return lambda([](nil<n>..., auto& e, auto ...) -> auto&
{
return *e;
});
}
(std::make_index_sequence<N>());
}

~luple()
{
lambda([](storage<Args>&... s)
{
(..., s->~Args());
});
}

private:
template <size_t N>
struct nil
{
template <typename T>
nil(T&&)
{
}
};

template <typename T>
class alignas(T) storage
{
public:
storage() = default;

template <typename... Brgs>
constexpr void init(Brgs&&... args)
{
new (reinterpret_cast<T*>(std::addressof(data))) T(std::forward<Brgs>(args)...);
}

T* operator->()
{
return reinterpret_cast<T*>(std::addressof(data));
}

const T* operator->() const
{
return reinterpret_cast<const T*>(std::addressof(data));
}

T& operator*()
{
return *operator->();
}

const T& operator*() const
{
return *operator->();
}

private:
char data[sizeof(T)];
};

template <typename... Brgs>
static constexpr decltype(auto) to_lambda(Brgs... brgs)
{
return [=](auto f) mutable -> decltype(auto)
{
return f(brgs...);
};
}

mutable decltype(to_lambda(storage<Args>()...)) lambda = to_lambda(storage<Args>()...);
};

template <typename... Args>
luple(Args...) -> luple<Args...>;

template <typename... Args>
luple(const luple<Args...>&) -> luple<Args...>;

template <typename T>
struct is_luple : std::false_type
{
};

template <typename... Args>
struct is_luple<luple<Args...>> : std::true_type
{
};

template <typename T>
inline constexpr auto is_luple_v = is_luple<T>::value;

template <typename T>
struct luple_size;

template <typename... Args>
struct luple_size<luple<Args...>> : std::integral_constant<size_t, sizeof...(Args)>
{
};

template <typename T>
inline constexpr size_t luple_size_v = luple_size<T>::value;

template <size_t N, typename T>
struct luple_element;

template <size_t N, typename... Args>
struct luple_element<N, luple<Args...>>
{
using type = std::remove_cvref_t<decltype(std::declval<luple<Args...>>().template get<N>())>;
};

template <size_t N, typename T>
using luple_element_t = typename luple_element<N, T>::type;

template <typename... Args>
constexpr decltype(auto) make_luple(Args&&... args)
{
return luple(static_cast<std::unwrap_ref_decay_t<Args>>(args)...);
}

template <typename... Args>
constexpr decltype(auto) luple_cat(Args&&... args)
{
auto t = make_luple(std::forward<Args>(args)...);

if constexpr(!sizeof...(Args))
return t;
else
{
return [&]<template <typename ...> typename T, template <auto ...> typename U, auto... m, auto... n>(T<U<m, n>...>)
{
return make_luple(t.template get<m>().template get<n>()...);
}
(rank_pack(std::forward<Args>(args)...));
}
}

template <typename T>
struct matrix_index_sequences
{
Expand Down
2 changes: 1 addition & 1 deletion include/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* time a set of code changes is merged to the master branch.
*/

#define MONSTER_VERSION_NUMBER 312
#define MONSTER_VERSION_NUMBER 313
#define MONSTER_VERSION_STRING "Monster/" MONSTER_STRINGIZE(MONSTER_VERSION_NUMBER)

#endif

0 comments on commit 06b65e0

Please sign in to comment.