1 // Copyright (c) 2016 Agustin Berge 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef HPX_UTIL_RANGE_HPP 7 #define HPX_UTIL_RANGE_HPP 8 9 #include <hpx/config.hpp> 10 11 #include <cstddef> 12 #include <iterator> 13 #include <utility> 14 15 namespace hpx { namespace util 16 { 17 namespace detail 18 { 19 /////////////////////////////////////////////////////////////////////// 20 template <typename T, std::size_t N> 21 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE begin_impl(T (& array)[N],long)22 T* begin_impl(T (&array)[N], long) noexcept 23 { 24 return &array[0]; 25 } 26 27 template <typename T, std::size_t N> 28 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE end_impl(T (& array)[N],long)29 T* end_impl(T (&array)[N], long) noexcept 30 { 31 return &array[N]; 32 } 33 34 template <typename T, std::size_t N> 35 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE size_impl(T const (& array)[N],long)36 std::size_t size_impl(T const (&array)[N], long) noexcept 37 { 38 return N; 39 } 40 41 template <typename T, std::size_t N> 42 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE empty_impl(T const (& array)[N],long)43 bool empty_impl(T const (&array)[N], long) noexcept 44 { 45 return false; 46 } 47 48 /////////////////////////////////////////////////////////////////////// 49 template <typename C, typename R = decltype(std::declval<C&>().begin())> 50 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE begin_impl(C & c,long)51 R begin_impl(C& c, long) 52 noexcept(noexcept(c.begin())) 53 { 54 return c.begin(); 55 } 56 57 template <typename C, typename R = decltype(std::declval<C&>().end())> 58 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE end_impl(C & c,long)59 R end_impl(C& c, long) 60 noexcept(noexcept(c.begin())) 61 { 62 return c.end(); 63 } 64 65 template <typename C, typename R = decltype(std::declval<C const&>().size())> 66 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE size_impl(C const & c,long)67 R size_impl(C const& c, long) 68 noexcept(noexcept(c.size())) 69 { 70 return c.size(); 71 } 72 73 template <typename C, typename R = decltype(std::declval<C const&>().empty())> 74 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE empty_impl(C const & c,long)75 R empty_impl(C const& c, long) 76 noexcept(noexcept(c.empty())) 77 { 78 return c.empty(); 79 } 80 81 /////////////////////////////////////////////////////////////////////// 82 namespace range_impl 83 { 84 struct fallback 85 { 86 template <typename T> fallbackhpx::util::detail::range_impl::fallback87 fallback(T const&){} 88 }; 89 90 fallback begin(fallback); 91 92 template <typename C, typename R = decltype(begin(std::declval<C&>()))> 93 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE begin_impl(C & c,int)94 R begin_impl(C& c, int) 95 noexcept(noexcept(begin(c))) 96 { 97 return begin(c); 98 } 99 100 fallback end(fallback); 101 102 template <typename C, typename R = decltype(end(std::declval<C&>()))> 103 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE end_impl(C & c,int)104 R end_impl(C& c, int) 105 noexcept(noexcept(end(c))) 106 { 107 return end(c); 108 } 109 } 110 using range_impl::begin_impl; 111 using range_impl::end_impl; 112 113 template <typename C> 114 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE size_impl(C const & c,int)115 std::size_t size_impl(C const& c, int) 116 { 117 return std::distance(begin_impl(c, 0L), end_impl(c, 0L)); 118 } 119 120 template <typename C> 121 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE empty_impl(C const & c,int)122 bool empty_impl(C const& c, int) 123 { 124 return begin_impl(c, 0L) == end_impl(c, 0L); 125 } 126 127 /////////////////////////////////////////////////////////////////////// 128 template <typename T> 129 struct result_of_begin 130 { 131 typedef decltype(detail::begin_impl(std::declval<T&>(), 0L)) type; 132 }; 133 134 template <typename T, typename Iter = typename result_of_begin<T>::type> 135 struct iterator 136 { 137 typedef Iter type; 138 }; 139 140 template <typename T> 141 struct iterator<T, range_impl::fallback> 142 {}; 143 144 /////////////////////////////////////////////////////////////////////// 145 template <typename T> 146 struct result_of_end 147 { 148 typedef decltype(detail::end_impl(std::declval<T&>(), 0L)) type; 149 }; 150 151 template <typename T, typename Iter = typename result_of_end<T>::type> 152 struct sentinel 153 { 154 typedef Iter type; 155 }; 156 157 template <typename T> 158 struct sentinel<T, range_impl::fallback> 159 {}; 160 } 161 162 /////////////////////////////////////////////////////////////////////////// 163 namespace range_adl 164 { 165 template < 166 typename C, 167 typename Iterator = typename detail::iterator<C>::type> 168 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE begin(C & c)169 Iterator begin(C& c) 170 noexcept(noexcept(detail::begin_impl(c, 0L))) 171 { 172 return detail::begin_impl(c, 0L); 173 } 174 175 template < 176 typename C, 177 typename Iterator = typename detail::iterator<C const>::type> 178 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE begin(C const & c)179 Iterator begin(C const& c) 180 noexcept(noexcept(detail::begin_impl(c, 0L))) 181 { 182 return detail::begin_impl(c, 0L); 183 } 184 185 template < 186 typename C, 187 typename Sentinel = typename detail::sentinel<C>::type> 188 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE end(C & c)189 Sentinel end(C& c) 190 noexcept(noexcept(detail::end_impl(c, 0L))) 191 { 192 return detail::end_impl(c, 0L); 193 } 194 195 template < 196 typename C, 197 typename Sentinel = typename detail::sentinel<C const>::type> 198 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE end(C const & c)199 Sentinel end(C const& c) 200 noexcept(noexcept(detail::end_impl(c, 0L))) 201 { 202 return detail::end_impl(c, 0L); 203 } 204 205 template < 206 typename C, 207 typename Iterator = typename detail::iterator<C const>::type, 208 typename Sentinel = typename detail::sentinel<C const>::type> 209 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE size(C const & c)210 std::size_t size(C const& c) 211 noexcept(noexcept(detail::size_impl(c, 0L))) 212 { 213 return detail::size_impl(c, 0L); 214 } 215 216 template < 217 typename C, 218 typename Iterator = typename detail::iterator<C const>::type, 219 typename Sentinel = typename detail::sentinel<C const>::type> 220 HPX_HOST_DEVICE HPX_CONSTEXPR HPX_FORCEINLINE empty(C const & c)221 bool empty(C const& c) 222 noexcept(noexcept(detail::empty_impl(c, 0L))) 223 { 224 return detail::empty_impl(c, 0L); 225 } 226 } 227 using namespace range_adl; 228 }} 229 230 #endif /*HPX_UTIL_RANGE_HPP*/ 231