| 1 | #pragma once |
| 2 | |
| 3 | #include <type_traits> |
| 4 | #include <boost/range/counting_range.hpp> |
| 5 | #include <boost/range/adaptor/transformed.hpp> |
| 6 | |
| 7 | |
| 8 | namespace ext |
| 9 | { |
| 10 | /// For loop adaptor which is used to iterate through a half-closed interval [begin, end). |
| 11 | template <typename BeginType, typename EndType> |
| 12 | inline auto range(BeginType begin, EndType end) |
| 13 | { |
| 14 | using CommonType = typename std::common_type<BeginType, EndType>::type; |
| 15 | return boost::counting_range<CommonType>(begin, end); |
| 16 | } |
| 17 | |
| 18 | template <typename Type> |
| 19 | inline auto range(Type end) |
| 20 | { |
| 21 | return range<Type, Type>(static_cast<Type>(0), end); |
| 22 | } |
| 23 | |
| 24 | /// The same as range(), but every value is casted statically to a specified `ValueType`. |
| 25 | /// This is useful to iterate through all constants of a enum. |
| 26 | template <typename ValueType, typename BeginType, typename EndType> |
| 27 | inline auto range_with_static_cast(BeginType begin, EndType end) |
| 28 | { |
| 29 | using CommonType = typename std::common_type<BeginType, EndType>::type; |
| 30 | if constexpr (std::is_same_v<ValueType, CommonType>) |
| 31 | return boost::counting_range<CommonType>(begin, end); |
| 32 | else |
| 33 | return boost::counting_range<CommonType>(begin, end) |
| 34 | | boost::adaptors::transformed([](CommonType x) -> ValueType { return static_cast<ValueType>(x); }); |
| 35 | } |
| 36 | |
| 37 | template <typename ValueType, typename EndType> |
| 38 | inline auto range_with_static_cast(EndType end) |
| 39 | { |
| 40 | return range_with_static_cast<ValueType, EndType, EndType>(static_cast<EndType>(0), end); |
| 41 | } |
| 42 | } |
| 43 | |