#ifndef BASE_RANGES_RANGES_H_
#define BASE_RANGES_RANGES_H_
#include <array>
#include <iterator>
#include <type_traits>
#include <utility>
#include "base/template_util.h"
namespace base {
namespace internal {
template <typename T, size_t N>
constexpr T* begin(T (&array)[N], priority_tag<2>) {
return array;
}
template <typename T, size_t N>
constexpr T* begin(std::array<T, N>& array, priority_tag<2> tag) {
return const_cast<T*>(begin(const_cast<const std::array<T, N>&>(array), tag));
}
#if !defined(CEF_EXCLUDE_PROBLEMATIC_CONST_ARRAY_OVERLOADS)
template <typename T, size_t N>
constexpr const T* begin(const std::array<T, N>& array, priority_tag<2>) {
return N != 0 ? &array[0] : nullptr;
}
#endif
template <typename Range>
constexpr auto begin(Range&& range, priority_tag<1>)
-> decltype(std::forward<Range>(range).begin()) {
return std::forward<Range>(range).begin();
}
template <typename Range>
constexpr auto begin(Range&& range, priority_tag<0>)
-> decltype(begin(std::forward<Range>(range))) {
return begin(std::forward<Range>(range));
}
template <typename T, size_t N>
constexpr T* end(T (&array)[N], priority_tag<2>) {
return array + N;
}
template <typename T, size_t N>
constexpr T* end(std::array<T, N>& array, priority_tag<2> tag) {
return const_cast<T*>(end(const_cast<const std::array<T, N>&>(array), tag));
}
#if !defined(CEF_EXCLUDE_PROBLEMATIC_CONST_ARRAY_OVERLOADS)
template <typename T, size_t N>
constexpr const T* end(const std::array<T, N>& array, priority_tag<2>) {
return N != 0 ? (&array[0]) + N : nullptr;
}
#endif
template <typename Range>
constexpr auto end(Range&& range, priority_tag<1>)
-> decltype(std::forward<Range>(range).end()) {
return std::forward<Range>(range).end();
}
template <typename Range>
constexpr auto end(Range&& range, priority_tag<0>)
-> decltype(end(std::forward<Range>(range))) {
return end(std::forward<Range>(range));
}
}
namespace ranges {
template <typename Range>
constexpr auto begin(Range&& range) noexcept
-> decltype(internal::begin(std::forward<Range>(range),
internal::priority_tag<2>())) {
return internal::begin(std::forward<Range>(range),
internal::priority_tag<2>());
}
template <typename Range>
constexpr auto end(Range&& range) noexcept
-> decltype(internal::end(std::forward<Range>(range),
internal::priority_tag<2>())) {
return internal::end(std::forward<Range>(range), internal::priority_tag<2>());
}
template <typename Range>
using iterator_t = decltype(ranges::begin(std::declval<Range&>()));
template <typename Range>
using range_value_t = iter_value_t<iterator_t<Range>>;
}
}
#endif