#pragma once #include #include #include namespace ext { namespace internal { template auto rangeImpl(BeginType begin, EndType end) { if constexpr (std::is_same_v) return boost::counting_range(static_cast(begin), static_cast(end)); else return boost::counting_range(static_cast(begin), static_cast(end)) | boost::adaptors::transformed([](CountingType x) { return static_cast(x); }); } } /// For loop adaptor which is used to iterate through a half-closed interval [begin, end). /// The parameters `begin` and `end` can have any integral or enum types. template || std::is_enum_v) && (std::is_integral_v || std::is_enum_v) && (!std::is_enum_v || !std::is_enum_v || std::is_same_v), void>> inline auto range(BeginType begin, EndType end) { if constexpr (std::is_integral_v && std::is_integral_v) { using CommonType = std::common_type_t; return internal::rangeImpl(begin, end); } else if constexpr (std::is_enum_v) { return internal::rangeImpl>(begin, end); } else { return internal::rangeImpl>(begin, end); } } /// For loop adaptor which is used to iterate through a half-closed interval [0, end). /// The parameter `end` can have any integral or enum type. /// The same as range(0, end). template || std::is_enum_v, void>> inline auto range(Type end) { if constexpr (std::is_integral_v) return internal::rangeImpl(0, end); else return internal::rangeImpl>(0, end); } }