Skip to content

Instantly share code, notes, and snippets.

@juliusHuelsmann
Last active February 18, 2020 17:35
Show Gist options
  • Save juliusHuelsmann/669f537aeb5e7105386d510d186b24e1 to your computer and use it in GitHub Desktop.
Save juliusHuelsmann/669f537aeb5e7105386d510d186b24e1 to your computer and use it in GitHub Desktop.
Code snipplet (c++20) for creating conditional tuples; getting a conditional tuple type.
// Author: Julius Hülsmann
// Email: juliusHuelsmann [at] gmail.com, julius.huelsmann [at] data-spree.com
// Creation Date: 2020-02-17
// Execution: g++-10.0 -std=c++2a [FILE]
#include <initializer_list>
#include <tuple>
#include <utility>
//#define EXECUTION consteval //< c++2a
#define EXECUTION constexpr //< prior to cpp 20 XXX: switch if compiled with g++ < 10
namespace dbn {
/// Helper struct which allows functions in order to remove certain values from an instance of a
/// tuple.
template <bool condition, std::size_t s> struct tuple {
/// Retain first \p s values from the tuple \p tpl.
template <typename Tuple> static inline EXECUTION auto retain(Tuple const &tpl) noexcept {
static_assert(s <= std::tuple_size<Tuple>::value, "Invalid tuple reduction size!");
constexpr auto k = condition ? s : std::tuple_size<Tuple>::value;
return _reduce(tpl, std::make_index_sequence<s>());
}
/// Strip last \p s values from the tuple \p tpl.
template <typename Tuple> static inline EXECUTION auto strip(Tuple const &tpl) noexcept {
static_assert(s >= 0 && s < std::tuple_size<Tuple>::value, "Invalid tuple reduction size!");
constexpr auto k = condition ? s : 0;
return _reduce(tpl, std::make_index_sequence<std::tuple_size<Tuple>::value - s>());
}
private:
template <typename Tuple, std::size_t... I>
static inline EXECUTION auto _reduce(Tuple const &tpl, std::index_sequence<I...>) noexcept {
return std::make_tuple(std::get<I>(tpl)...);
}
};
/// Helper struct which operates on the type of a tuple and instead of the instance as is the case
/// in @cmp #tuple.
template <bool cond, size_t s, typename is, typename ...args> struct thlp;
template <bool cond, size_t s, size_t... i, class... args>
struct thlp<cond, s, std::index_sequence<i...>, args...> {
static_assert(s <= sizeof...(args), "Requested new tuple size exceeds old one.");
using type = std::tuple<std::tuple_element_t<i, std::tuple<args...>>...>;
};
template <size_t s, size_t... i, class... a> struct thlp<false, s, std::index_sequence<i...>,a...> {
using type = std::tuple<a...>;
};
/// Strips sizeof...\p args - \p elementsToKeep last types from tuple if indicated by \p condition.
template <bool condition, size_t keep, typename... args>
using conditional_tuple_t = thlp<condition, keep,
decltype(std::make_index_sequence<keep>()), args...>::type;
} // namespace dbn
int main() {
// Demonstrate usage of the type
dbn::conditional_tuple_t<true, 2, int, int, double> fa = std::make_tuple(1, 2);
// Demonstration of the value
auto const [a, b] = dbn::tuple<true, 2>::retain(std::make_tuple(1, 2, 4));
auto const [aa, bb, c] = dbn::tuple<true, 3>::retain(std::make_tuple(1, 2, 4));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment