2015-10-05 00:33:43 +00:00
|
|
|
#pragma once
|
|
|
|
|
2019-11-24 15:03:30 +00:00
|
|
|
#include <boost/range/counting_range.hpp>
|
|
|
|
#include <boost/range/adaptor/transformed.hpp>
|
2020-05-02 16:05:01 +00:00
|
|
|
#include <type_traits>
|
2017-06-13 02:30:24 +00:00
|
|
|
|
2015-10-05 00:33:43 +00:00
|
|
|
|
|
|
|
namespace ext
|
|
|
|
{
|
2020-05-02 16:05:01 +00:00
|
|
|
namespace internal
|
|
|
|
{
|
|
|
|
template <typename ResultType, typename CountingType, typename BeginType, typename EndType>
|
|
|
|
auto rangeImpl(BeginType begin, EndType end)
|
2017-06-06 17:10:04 +00:00
|
|
|
{
|
2020-05-02 16:05:01 +00:00
|
|
|
if constexpr (std::is_same_v<ResultType, CountingType>)
|
|
|
|
return boost::counting_range<CountingType>(static_cast<CountingType>(begin), static_cast<CountingType>(end));
|
|
|
|
else
|
|
|
|
return boost::counting_range<CountingType>(static_cast<CountingType>(begin), static_cast<CountingType>(end))
|
|
|
|
| boost::adaptors::transformed([](CountingType x) { return static_cast<ResultType>(x); });
|
2019-11-24 15:03:30 +00:00
|
|
|
}
|
2020-05-02 16:05:01 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 00:33:43 +00:00
|
|
|
|
2020-05-02 16:05:01 +00:00
|
|
|
/// 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 <typename BeginType,
|
|
|
|
typename EndType,
|
|
|
|
typename = std::enable_if_t<
|
|
|
|
(std::is_integral_v<BeginType> || std::is_enum_v<BeginType>) &&
|
|
|
|
(std::is_integral_v<EndType> || std::is_enum_v<EndType>) &&
|
|
|
|
(!std::is_enum_v<BeginType> || !std::is_enum_v<EndType> || std::is_same_v<BeginType, EndType>), void>>
|
|
|
|
inline auto range(BeginType begin, EndType end)
|
|
|
|
{
|
|
|
|
if constexpr (std::is_integral_v<BeginType> && std::is_integral_v<EndType>)
|
2019-11-24 15:03:30 +00:00
|
|
|
{
|
2020-05-02 16:05:01 +00:00
|
|
|
using CommonType = std::common_type_t<BeginType, EndType>;
|
|
|
|
return internal::rangeImpl<CommonType, CommonType>(begin, end);
|
2019-11-24 15:03:30 +00:00
|
|
|
}
|
2020-05-02 16:05:01 +00:00
|
|
|
else if constexpr (std::is_enum_v<BeginType>)
|
2019-11-24 15:03:30 +00:00
|
|
|
{
|
2020-05-02 16:05:01 +00:00
|
|
|
return internal::rangeImpl<BeginType, std::underlying_type_t<BeginType>>(begin, end);
|
2019-11-24 15:03:30 +00:00
|
|
|
}
|
2020-05-02 16:05:01 +00:00
|
|
|
else
|
2017-06-06 17:10:04 +00:00
|
|
|
{
|
2020-05-02 16:05:01 +00:00
|
|
|
return internal::rangeImpl<EndType, std::underlying_type_t<EndType>>(begin, end);
|
2017-06-06 17:10:04 +00:00
|
|
|
}
|
2015-10-05 00:33:43 +00:00
|
|
|
}
|
2020-05-02 16:05:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
/// 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 <typename Type,
|
|
|
|
typename = std::enable_if_t<std::is_integral_v<Type> || std::is_enum_v<Type>, void>>
|
|
|
|
inline auto range(Type end)
|
|
|
|
{
|
|
|
|
if constexpr (std::is_integral_v<Type>)
|
|
|
|
return internal::rangeImpl<Type, Type>(0, end);
|
|
|
|
else
|
|
|
|
return internal::rangeImpl<Type, std::underlying_type_t<Type>>(0, end);
|
|
|
|
}
|
|
|
|
}
|