mirror of
				https://github.com/pocketpy/pocketpy
				synced 2025-10-26 14:30:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			216 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			216 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /***************************************************************************
 | |
| * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht          *
 | |
| * Copyright (c) QuantStack                                                 *
 | |
| *                                                                          *
 | |
| * Distributed under the terms of the BSD 3-Clause License.                 *
 | |
| *                                                                          *
 | |
| * The full license is in the file LICENSE, distributed with this software. *
 | |
| ****************************************************************************/
 | |
| 
 | |
| #ifndef XTL_SEQUENCE_HPP
 | |
| #define XTL_SEQUENCE_HPP
 | |
| 
 | |
| #include <array>
 | |
| #include <cstddef>
 | |
| #include <type_traits>
 | |
| #include <utility>
 | |
| #include <vector>
 | |
| 
 | |
| #include "xtl_config.hpp"
 | |
| #include "xmeta_utils.hpp"
 | |
| 
 | |
| namespace xtl
 | |
| {
 | |
|     template <class S>
 | |
|     S make_sequence(typename S::size_type size);
 | |
| 
 | |
|     template <class S>
 | |
|     S make_sequence(typename S::size_type size, typename S::value_type v);
 | |
| 
 | |
|     template <class S>
 | |
|     S make_sequence(std::initializer_list<typename S::value_type> init);
 | |
| 
 | |
|     template <class R, class A>
 | |
|     decltype(auto) forward_sequence(A&& s);
 | |
| 
 | |
|     // equivalent to std::size(c) in c++17
 | |
|     template <class C>
 | |
|     constexpr auto sequence_size(const C& c) -> decltype(c.size());
 | |
| 
 | |
|     // equivalent to std::size(a) in c++17
 | |
|     template <class T, std::size_t N>
 | |
|     constexpr std::size_t sequence_size(const T (&a)[N]);
 | |
| 
 | |
|     /********************************
 | |
|      * make_sequence implementation *
 | |
|      ********************************/
 | |
| 
 | |
|     namespace detail
 | |
|     {
 | |
|         template <class S>
 | |
|         struct sequence_builder
 | |
|         {
 | |
|             using value_type = typename S::value_type;
 | |
|             using size_type = typename S::size_type;
 | |
| 
 | |
|             inline static S make(size_type size)
 | |
|             {
 | |
|                 return S(size);
 | |
|             }
 | |
| 
 | |
|             inline static S make(size_type size, value_type v)
 | |
|             {
 | |
|                 return S(size, v);
 | |
|             }
 | |
| 
 | |
|             inline static S make(std::initializer_list<value_type> init)
 | |
|             {
 | |
|                 return S(init);
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         template <class T, std::size_t N>
 | |
|         struct sequence_builder<std::array<T, N>>
 | |
|         {
 | |
|             using sequence_type = std::array<T, N>;
 | |
|             using value_type = typename sequence_type::value_type;
 | |
|             using size_type = typename sequence_type::size_type;
 | |
| 
 | |
|             inline static sequence_type make(size_type /*size*/)
 | |
|             {
 | |
|                 return sequence_type();
 | |
|             }
 | |
| 
 | |
|             inline static sequence_type make(size_type /*size*/, value_type v)
 | |
|             {
 | |
|                 sequence_type s;
 | |
|                 s.fill(v);
 | |
|                 return s;
 | |
|             }
 | |
| 
 | |
|             inline static sequence_type make(std::initializer_list<value_type> init)
 | |
|             {
 | |
|                 sequence_type s;
 | |
|                 std::copy(init.begin(), init.end(), s.begin());
 | |
|                 return s;
 | |
|             }
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     template <class S>
 | |
|     inline S make_sequence(typename S::size_type size)
 | |
|     {
 | |
|         return detail::sequence_builder<S>::make(size);
 | |
|     }
 | |
| 
 | |
|     template <class S>
 | |
|     inline S make_sequence(typename S::size_type size, typename S::value_type v)
 | |
|     {
 | |
|         return detail::sequence_builder<S>::make(size, v);
 | |
|     }
 | |
| 
 | |
|     template <class S>
 | |
|     inline S make_sequence(std::initializer_list<typename S::value_type> init)
 | |
|     {
 | |
|         return detail::sequence_builder<S>::make(init);
 | |
|     }
 | |
| 
 | |
|     /***********************************
 | |
|      * forward_sequence implementation *
 | |
|      ***********************************/
 | |
| 
 | |
|     namespace detail
 | |
|     {
 | |
|         template <class R, class A, class E = void>
 | |
|         struct sequence_forwarder_impl
 | |
|         {
 | |
|             template <class T>
 | |
|             static inline R forward(const T& r)
 | |
|             {
 | |
|                 R ret;
 | |
|                 std::copy(std::begin(r), std::end(r), std::begin(ret));
 | |
|                 return ret;
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         template <class R, class A>
 | |
|         struct sequence_forwarder_impl<R, A, void_t<decltype(std::declval<R>().resize(
 | |
|               std::declval<std::size_t>()))>>
 | |
|         {
 | |
|             template <class T>
 | |
|             static inline auto forward(const T& r)
 | |
|             {
 | |
|                 return R(std::begin(r), std::end(r));
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         template <class R, class A>
 | |
|         struct sequence_forwarder
 | |
|             : sequence_forwarder_impl<R, A>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class R>
 | |
|         struct sequence_forwarder<R, R>
 | |
|         {
 | |
|             template <class T>
 | |
|             static inline T&& forward(T&& t) noexcept
 | |
|             {
 | |
|                 return std::forward<T>(t);
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         template <class R, class A>
 | |
|         using forwarder_type = detail::sequence_forwarder<
 | |
|             std::decay_t<R>,
 | |
|             std::remove_cv_t<std::remove_reference_t<A>>
 | |
|         >;
 | |
|     }
 | |
| 
 | |
|     template <class R, class A>
 | |
|     inline decltype(auto) forward_sequence(typename std::remove_reference<A>::type& s)
 | |
|     {
 | |
|         using forwarder = detail::forwarder_type<R, A>;
 | |
|         return forwarder::forward(std::forward<A>(s));
 | |
|     }
 | |
| 
 | |
|     template <class R, class A>
 | |
|     inline decltype(auto) forward_sequence(typename std::remove_reference<A>::type&& s)
 | |
|     {
 | |
|         using forwarder = detail::forwarder_type<R, A>;
 | |
|         static_assert(!std::is_lvalue_reference<A>::value,
 | |
|                       "Can not forward an rvalue as an lvalue.");
 | |
|         return forwarder::forward(std::move(s));
 | |
|     }
 | |
| 
 | |
|     /********************************
 | |
|      * sequence_size implementation *
 | |
|      ********************************/
 | |
| 
 | |
|     // equivalent to std::size(c) in c++17
 | |
|     template <class C>
 | |
|     constexpr auto sequence_size(const C& c) -> decltype(c.size())
 | |
|     {
 | |
|         return c.size();
 | |
|     }
 | |
| 
 | |
|     // equivalent to std::size(a) in c++17
 | |
|     template <class T, std::size_t N>
 | |
|     constexpr std::size_t sequence_size(const T (&)[N])
 | |
|     {
 | |
|         return N;
 | |
|     }
 | |
| 
 | |
|     /****************************
 | |
|      * are_equivalent_sequences *
 | |
|      ****************************/
 | |
| 
 | |
|     template <class E1, class E2>
 | |
|     inline bool are_equivalent_sequences(const E1& e1, const E2& e2)
 | |
|     {
 | |
|         return std::equal(e1.cbegin(), e1.cend(), e2.cbegin(), e2.cend());
 | |
|     }
 | |
| }
 | |
| 
 | |
| #endif
 |