Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- /*
- A stand-alone zip implementation from the FGL Library
- Doxygen comments removed. Refer to documentation.
- This is a merger of constexpr_assert.hpp and zip.hpp
- Documentation: https://alaestor.github.io/libFGL/group__group-utility-zip.html
- Repo: https://github.com/alaestor/libFGL
- My discord: Honshitsu#9218 or visit http://discord.0x04.cc
- Quick example program:
- // Output: 1 1.2 hi, 2 2.2 bye, 3 3.2 lol,
- #include <iostream>
- #include <vector>
- #include <array>
- #include <list>
- int main()
- {
- std::vector my_vec{ 1,2,3,4,5,6 };
- std::array my_arr{ 1.2,2.2,3.2,4.2,5.2 };
- std::list my_list{ "hi", "bye", "lol" };
- for (const auto& [a, b, c] : fgl::czip(my_vec, my_arr, my_list))
- std::cout << a << " " << b << " " << c << ", ";
- std::cout << std::endl;
- }
- */
- // INLINED FILE -> fgl/debug/constexpr_assert.hpp
- #ifndef FGL_DEBUG_CONSTEXPR_ASSERT_HPP_INCLUDED
- #define FGL_DEBUG_CONSTEXPR_ASSERT_HPP_INCLUDED
- #include <type_traits> // is_constant_evaluated
- #include <cassert>
- #ifdef NDEBUG
- #ifndef FGL_DEBUG_CONSTEXPR_ASSERT
- #define FGL_DEBUG_CONSTEXPR_ASSERT(assertion)
- #else
- #error FGL_DEBUG_CONSTEXPR_ASSERT already defined
- #endif // ifndef FGL_DEBUG_CONSTEXPR_ASSERT
- #else
- #ifndef FGL_DEBUG_CONSTEXPR_ASSERT
- #define FGL_DEBUG_CONSTEXPR_ASSERT(assertion) \
- if (std::is_constant_evaluated())\
- {\
- _Pragma("GCC diagnostic push")\
- _Pragma("GCC diagnostic ignored \"-Wterminate\"")\
- _Pragma("GCC diagnostic ignored \"-Wuseless-cast\"")\
- if (static_cast<bool>(assertion) == false)\
- { throw; } /* ASSERTION FAILED */\
- _Pragma("GCC diagnostic pop")\
- }\
- else assert((assertion));
- #else
- #error FGL_DEBUG_CONSTEXPR_ASSERT already defined
- #endif // ifndef FGL_DEBUG_CONSTEXPR_ASSERT
- #endif // ifdef NDEBUG else
- #ifdef FGL_SHORT_MACROS
- #define FGL_DEBUG_CONSTEXPR_ASSERT_SHORT_MACROS
- #endif // ifdef FGL_SIMPLE_MACROS
- #ifdef FGL_DEBUG_CONSTEXPR_ASSERT_SHORT_MACROS
- #ifndef constexpr_assert
- #define constexpr_assert(assertion) \
- FGL_DEBUG_CONSTEXPR_ASSERT(assertion)
- #else
- #error constexpr_assert already defined
- #endif // constexpr_assertS
- #endif // ifdef FGL_DEBUG_CONSTEXPR_ASSERT_SHORT_MACRO
- #endif // ifndef FGL_DEBUG_CONSTEXPR_ASSERT_HPP_INCLUDED
- // INLINED FILE -> fgl/utility/zip.hpp
- #ifndef FGL_UTILITY_ZIP_HPP_INCLUDED
- #define FGL_UTILITY_ZIP_HPP_INCLUDED
- #include <cstddef> // size_t, ptrdiff_t
- #include <functional> // ref
- #include <iterator>
- #include <tuple>
- #include <ranges>
- namespace fgl {
- using zip_sentinel_t = std::ptrdiff_t;
- namespace internal {
- template <std::forward_iterator ... T_iters>
- class forward_zip_iterator final
- {
- zip_sentinel_t m_index{ 0 };
- std::tuple<T_iters...> m_iters;
- // maybe an easier way but oh well
- [[nodiscard]] static constexpr auto accessType(auto& v) noexcept
- { return std::ref(v); }
- [[nodiscard]] static constexpr auto accessType(auto&& v) noexcept
- { return v; }
- template <std::forward_iterator T>
- using get_iter_ref_t = typename std::iterator_traits<T>::reference;
- public:
- using value_type = std::tuple<get_iter_ref_t<T_iters>...>;
- using difference_type = decltype(m_index);
- using iterator_category = std::forward_iterator_tag;
- [[nodiscard]] explicit constexpr forward_zip_iterator() noexcept
- = default; // Getting a redefinition error? T_iters mustn't be empty.
- [[nodiscard]] explicit constexpr forward_zip_iterator(T_iters&& ... args)
- : m_iters(std::forward<T_iters>(args)...)
- { static_assert(std::forward_iterator<forward_zip_iterator<T_iters...>>); }
- constexpr forward_zip_iterator& operator++() noexcept
- {
- ++m_index;
- std::apply([](auto && ... args) noexcept { ((++args),...); }, m_iters);
- return *this;
- }
- [[nodiscard]] constexpr forward_zip_iterator operator++(int)
- {
- forward_zip_iterator tmp = *this;
- ++*this;
- return tmp;
- }
- [[nodiscard]] [[deprecated("Expensive & internal. Use difference_type.")]]
- constexpr bool operator==(const forward_zip_iterator& rhs) const
- {
- const auto any_iterators_match{
- [&]<std::size_t ... i>(std::index_sequence<i...>) constexpr -> bool
- { return ((std::get<i>(m_iters)==std::get<i>(rhs.m_iters))||...); }
- };
- return any_iterators_match(std::index_sequence_for<T_iters...>());
- }
- [[nodiscard]] constexpr
- bool operator==(const difference_type index) const noexcept
- { return m_index == index; }
- [[nodiscard]] constexpr
- auto operator<=>(const difference_type index) const noexcept
- { return m_index <=> index; }
- [[nodiscard]] constexpr difference_type index() const noexcept
- { return m_index; }
- [[nodiscard]] constexpr value_type operator*() const
- noexcept( (noexcept(*T_iters{}) && ...) )
- {
- return [&]<std::size_t ... i>(std::index_sequence<i...>) -> value_type
- {
- return std::tuple(accessType(*std::get<i>(m_iters))...);
- }(std::index_sequence_for<T_iters...>());
- }
- };
- static_assert(std::forward_iterator<forward_zip_iterator<char*>>);
- static_assert(std::forward_iterator<forward_zip_iterator<const char*>>);
- static_assert(
- std::sentinel_for
- <
- forward_zip_iterator<const double*>::difference_type,
- forward_zip_iterator<const double*>
- >
- );
- [[nodiscard]] constexpr inline
- zip_sentinel_t shortest(const std::integral auto& ... lengths)
- {
- return std::min({static_cast<zip_sentinel_t>(lengths)...});
- }
- }// namespace internal
- template <std::ranges::forward_range ... T_ranges>
- constexpr auto zip(const std::integral auto length, T_ranges&& ... ranges)
- {
- FGL_DEBUG_CONSTEXPR_ASSERT(
- static_cast<zip_sentinel_t>(length)
- <= internal::shortest(std::ranges::ssize(ranges)...)
- );
- using fgl::internal::forward_zip_iterator;
- return std::ranges::subrange(
- forward_zip_iterator(std::begin(std::forward<T_ranges>(ranges))...),
- static_cast<zip_sentinel_t>(length)
- );
- }
- template <std::ranges::forward_range ... T_ranges>
- constexpr auto zip(T_ranges&& ... ranges)
- {
- return fgl::zip(
- internal::shortest(std::ranges::ssize(ranges)...),
- std::forward<T_ranges>(ranges)...
- );
- }
- template <std::ranges::forward_range ... T_ranges>
- constexpr auto czip(const std::integral auto length, T_ranges&& ... args)
- {
- FGL_DEBUG_CONSTEXPR_ASSERT(
- static_cast<zip_sentinel_t>(length)
- <= internal::shortest(std::ranges::ssize(args)...)
- );
- using fgl::internal::forward_zip_iterator;
- return std::ranges::subrange(
- forward_zip_iterator(std::cbegin(std::forward<T_ranges>(args))...),
- static_cast<zip_sentinel_t>(length)
- );
- }
- template <std::ranges::forward_range ... T_ranges>
- constexpr auto czip(T_ranges&& ... args)
- {
- using internal::shortest, std::ranges::ssize;
- return fgl::czip(shortest(ssize(args)...), std::forward<T_ranges>(args)...);
- }
- } // namespace fgl
- #endif // FGL_UTILITY_ZIP_HPP_INCLUDED
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement