onilink_

Untitled

Feb 14th, 2019
299
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.89 KB | None | 0 0
  1. #ifndef ONIDEV_CORE_GSL_SPAN
  2. #define ONIDEV_CORE_GSL_SPAN
  3.  
  4. #include <onidev/core/contract.h>
  5. #include <cstddef>
  6. #include <memory>
  7.  
  8. // c++11 onidev's version of gsl::span
  9.  
  10. // https://github.com/martinmoene/gsl-lite/blob/master/include/gsl/gsl-lite.h
  11.  
  12. namespace od
  13. {
  14. inline namespace gsl
  15. {
  16.  
  17. template< class T, class U >
  18. inline constexpr T narrow_cast(U && u) noexcept
  19. {
  20.     return static_cast<T>( std::forward<U>( u ) );
  21. }
  22.  
  23. // tag to select span constructor taking a container
  24. struct with_container_t{
  25.     constexpr with_container_t(){}
  26. } constexpr with_container;
  27.  
  28. template<class T>
  29. class span
  30. {
  31.     template<class U> friend class span;
  32.  
  33. public:
  34.     typedef std::ptrdiff_t index_type;
  35.     typedef T element_type;
  36.     typedef T& reference;
  37.     typedef T* pointer;
  38.     typedef T const* const_pointer;
  39.     typedef T const& const_reference;
  40.    
  41.     typedef pointer iterator;
  42.     typedef const_pointer const_iterator;
  43.    
  44.     typedef std::reverse_iterator<iterator> reverse_iterator;
  45.     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  46.  
  47.     typedef typename std::iterator_traits<iterator>::difference_type difference_type;
  48.    
  49.     span() noexcept:
  50.         _first(nullptr),
  51.         _last (nullptr)
  52.     {
  53.         Expects(size() == 0);
  54.     }
  55.  
  56.     span(std::nullptr_t, index_type size_in):
  57.         _first(nullptr),
  58.         _last (nullptr)
  59.     {
  60.         Expects(size_in == 0);
  61.     }
  62.  
  63.     span(reference data_in):
  64.         span(&data_in, 1)
  65.     {
  66.     }
  67.    
  68.     span(element_type &&) = delete;
  69.    
  70.     span(pointer first_in, pointer last_in):
  71.         _first(first_in),
  72.         _last (last_in )
  73.     {
  74.         Expects(first_in <= last_in);
  75.     }
  76.  
  77.     span(pointer data_in, index_type size_in):
  78.         _first( data_in ),
  79.         _last ( data_in + size_in )
  80.     {
  81.         Expects( size_in == 0 || (size_in > 0 && data_in != nullptr) );
  82.     }
  83.  
  84.     template<class U>
  85.     span(U*& data_in, index_type size_in):
  86.         _first(data_in),
  87.         _last (data_in + size_in)
  88.     {
  89.         Expects(size_in == 0 || (size_in > 0 && data_in != nullptr));
  90.     }
  91.  
  92.     template< class U >
  93.     span(U * const & data_in, index_type size_in):
  94.         _first(data_in),
  95.         _last (data_in + size_in)
  96.     {
  97.         Expects(size_in == 0 || (size_in > 0 && data_in != nullptr));
  98.     }
  99.    
  100.     template< class U, size_t N >
  101.     span(U (&arr)[N]):
  102.         _first( &arr[0] ),
  103.         _last ( &arr[0] + N )
  104.     {
  105.     }
  106.  
  107.     template< class U, size_t N >
  108.     span( std::array< U, N > & arr ):
  109.         _first( arr.data() ),
  110.         _last ( arr.data() + N )
  111.     {
  112.     }
  113.  
  114.     template< class U, size_t N >
  115.     span( std::array< U, N > const & arr ):
  116.         _first( arr.data() ),
  117.         _last ( arr.data() + N )
  118.     {
  119.     }
  120.  
  121.     // SFINAE enable only if Cont has a data() member function
  122.     template< class Cont, class = decltype(std::declval<Cont>().data()) >
  123.     span(Cont & cont):
  124.         _first( cont.data() ),
  125.         _last ( cont.data() + cont.size() )
  126.     {
  127.     }
  128.    
  129.     template< class Cont >
  130.     span( with_container_t, Cont & cont ):
  131.         _first( cont.size() == 0 ? nullptr : &cont[0] ),
  132.         _last ( cont.size() == 0 ? nullptr : &cont[0] + cont.size() )
  133.     {
  134.     }
  135.    
  136.     span( std::shared_ptr<element_type> const& ptr ):
  137.         _first( ptr.get() ),
  138.         _last ( ptr.get() ? ptr.get() + 1 : 0 )
  139.     {
  140.     }
  141.  
  142.     template< class ArrayElementType = typename std::add_pointer<element_type>::type >
  143.     span( std::unique_ptr<ArrayElementType> const & ptr, index_type count ):
  144.         _first( ptr.get() ),
  145.         _last ( ptr.get() + count )
  146.     {
  147.     }
  148.  
  149.     span( std::unique_ptr<element_type> const & ptr ):
  150.         _first( ptr.get() ),
  151.         _last ( ptr.get() ? ptr.get() + 1 : 0 )
  152.     {
  153.     }
  154.  
  155.     span(span &&) = default;
  156.     span(span const &) = default;
  157.  
  158.     template< class U >
  159.     span( span<U> const & other ):
  160.         _first( other.begin() ),
  161.         _last ( other.end() )
  162.     {
  163.     }
  164.  
  165.     span& operator=( span && ) = default;
  166.     span& operator=( span const & ) = default;
  167.  
  168.     span first( index_type count ) const noexcept
  169.     {
  170.         Expects( count <= this->size() );
  171.         return span( this->data(), count );
  172.     }
  173.  
  174.     span last( index_type count ) const noexcept
  175.     {
  176.         Expects( count <= this->size() );
  177.         return span( this->data() + this->size() - count, count );
  178.     }
  179.  
  180.     span subspan( index_type offset ) const noexcept
  181.     {
  182.         Expects( offset <= this->size() );
  183.         return span( this->data() + offset, this->length() - offset );
  184.     }
  185.  
  186.     span subspan( index_type offset, index_type count ) const noexcept
  187.     {
  188.         Expects( offset <= this->size() && count <= this->size() - offset );
  189.         return span( this->data() + offset, count );
  190.     }
  191.  
  192.     iterator begin() const noexcept
  193.     {
  194.         return iterator( _first );
  195.     }
  196.  
  197.     iterator end() const noexcept
  198.     {
  199.         return iterator( _last );
  200.     }
  201.  
  202.     const_iterator cbegin() const noexcept
  203.     {
  204.         return const_iterator( begin() );
  205.     }
  206.  
  207.     const_iterator cend() const noexcept
  208.     {
  209.         return const_iterator( end() );
  210.     }
  211.  
  212.     reverse_iterator rbegin() const noexcept
  213.     {
  214.         return reverse_iterator( end() );
  215.     }
  216.  
  217.     reverse_iterator rend() const noexcept
  218.     {
  219.         return reverse_iterator( begin() );
  220.     }
  221.  
  222.     const_reverse_iterator crbegin() const noexcept
  223.     {
  224.         return const_reverse_iterator( cend() );
  225.     }
  226.  
  227.     const_reverse_iterator crend() const noexcept
  228.     {
  229.         return const_reverse_iterator( cbegin() );
  230.     }
  231.  
  232.     reference operator[]( index_type index ) const
  233.     {
  234.        return at(index);
  235.     }
  236.  
  237.     reference operator()( index_type index ) const
  238.     {
  239.        return at(index);
  240.     }
  241.  
  242.     reference at(index_type index) const
  243.     {
  244.        Expects(index < size());
  245.        return _first[index];
  246.     }
  247.  
  248.     pointer data() const noexcept
  249.     {
  250.         return _first;
  251.     }
  252.  
  253.     bool empty() const noexcept
  254.     {
  255.         return size() == 0;
  256.     }
  257.  
  258.     index_type size() const noexcept
  259.     {
  260.         return _last - _first;
  261.     }
  262.  
  263.     index_type length() const noexcept
  264.     {
  265.         return size();
  266.     }
  267.  
  268.     index_type size_bytes() const noexcept
  269.     {
  270.         return size() * narrow_cast<index_type>( sizeof( element_type ) );
  271.     }
  272.  
  273.     index_type length_bytes() const noexcept
  274.     {
  275.         return size_bytes();
  276.     }
  277.  
  278.     void swap(span& other) noexcept
  279.     {
  280.         using std::swap;
  281.         swap( _first, other._first );
  282.         swap( _last , other._last  );
  283.     }
  284.    
  285.     template<class U>
  286.     span<U> as_span() const noexcept
  287.     {
  288.         Expects( ( this->size_bytes() % sizeof(U) ) == 0 );
  289.         return span< U >( reinterpret_cast<U *>( this->data() ), this->size_bytes() / sizeof( U ) );
  290.     }
  291.  
  292. private:
  293.     pointer _first;
  294.     pointer _last;
  295. };
  296.  
  297. }
  298.  
  299. }
  300.  
  301. #endif
Advertisement
Add Comment
Please, Sign In to add comment