1
0
Fork 0
mirror of https://github.com/bolero-MURAKAMI/Sprout synced 2025-08-03 12:49:50 +00:00

add subscript_at function

This commit is contained in:
bolero-MURAKAMI 2016-04-17 19:36:56 +09:00
parent 8278a2642c
commit 0080332dd5
12 changed files with 341 additions and 54 deletions

View file

@ -35,6 +35,7 @@ namespace sprout_adl {
sprout::not_found_via_adl range_empty(...);
sprout::not_found_via_adl range_front(...);
sprout::not_found_via_adl range_back(...);
sprout::not_found_via_adl range_subscript_at(...);
sprout::not_found_via_adl range_at(...);
sprout::not_found_via_adl range_nth(...);
sprout::not_found_via_adl range_index_of(...);
@ -585,6 +586,89 @@ namespace sprout {
return *sprout::next(sprout::begin(cont), sprout::size(cont) - 1);
}
template<typename T>
struct has_mem_subscript_test {
public:
template<
typename U = T,
typename = typename sprout::identity<decltype(std::declval<U>()[std::declval<typename sprout::container_traits<U>::size_type>()])>::type
>
static sprout::true_type test(int);
static sprout::false_type test(...);
};
#if defined(_MSC_VER) && (_MSC_VER > 1900)
template<typename T, typename Base_ = typename sprout::identity<decltype(sprout::detail::has_mem_subscript_test<T>::test(0))>::type>
struct has_mem_subscript
: public Base_
{};
#else
template<typename T>
struct has_mem_subscript
: public sprout::identity<decltype(sprout::detail::has_mem_subscript_test<T>::test(0))>::type
{};
#endif
template<typename T>
struct is_substitutable_const_subscript_at
: public sprout::bool_constant<
sprout::is_const_cast_convertible<
typename sprout::container_traits<T const>::reference,
typename sprout::container_traits<T>::reference
>::value
&& (
sprout::detail::has_mem_subscript<T const>::value
|| sprout::detail::has_mem_begin<T const>::value
|| sprout::detail::has_adl_begin_without_sprout<T const&>::value
)
>
{};
template<typename Container>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::detail::is_substitutable_const_subscript_at<Container>::value,
typename sprout::container_traits<Container>::reference
>::type
range_subscript_at_impl(Container& cont, typename sprout::container_traits<Container>::size_type i) {
typedef typename sprout::container_traits<Container>::reference type;
return const_cast<type>(sprout::subscript_at(sprout::as_const(cont), i));
}
template<typename Container>
inline SPROUT_CONSTEXPR typename std::enable_if<
!sprout::detail::is_substitutable_const_subscript_at<Container>::value
&& sprout::detail::has_mem_subscript<Container>::value
,
typename sprout::container_traits<Container>::reference
>::type
range_subscript_at_impl(Container& cont, typename sprout::container_traits<Container>::size_type i) {
return cont[i];
}
template<typename Container>
inline SPROUT_CONSTEXPR typename std::enable_if<
!sprout::detail::is_substitutable_const_subscript_at<Container>::value
&& !sprout::detail::has_mem_subscript<Container>::value
,
typename sprout::container_traits<Container>::reference
>::type
range_subscript_at_impl(Container& cont, typename sprout::container_traits<Container>::size_type i) {
return *sprout::next(sprout::begin(cont), i);
}
template<typename Container>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::detail::has_mem_subscript<Container const>::value,
typename sprout::container_traits<Container const>::reference
>::type
range_subscript_at_impl(Container const& cont, typename sprout::container_traits<Container const>::size_type i) {
return cont[i];
}
template<typename Container>
inline SPROUT_CONSTEXPR typename std::enable_if<
!sprout::detail::has_mem_subscript<Container const>::value,
typename sprout::container_traits<Container const>::reference
>::type
range_subscript_at_impl(Container const& cont, typename sprout::container_traits<Container const>::size_type i) {
return *sprout::next(sprout::begin(cont), i);
}
template<typename T>
struct has_mem_at_test {
public:
@ -616,6 +700,7 @@ namespace sprout {
>::value
&& (
sprout::detail::has_mem_at<T const>::value
|| sprout::detail::has_mem_subscript<T const>::value
|| sprout::detail::has_mem_begin<T const>::value
|| sprout::detail::has_adl_begin_without_sprout<T const&>::value
)
@ -645,11 +730,23 @@ namespace sprout {
inline SPROUT_CONSTEXPR typename std::enable_if<
!sprout::detail::is_substitutable_const_at<Container>::value
&& !sprout::detail::has_mem_at<Container>::value
&& sprout::detail::has_mem_subscript<Container>::value
,
typename sprout::container_traits<Container>::reference
>::type
range_at_impl(Container& cont, typename sprout::container_traits<Container>::size_type i) {
return *sprout::next(sprout::begin(cont), i);
return cont[sprout::range_index_check(cont, i)];
}
template<typename Container>
inline SPROUT_CONSTEXPR typename std::enable_if<
!sprout::detail::is_substitutable_const_at<Container>::value
&& !sprout::detail::has_mem_at<Container>::value
&& !sprout::detail::has_mem_subscript<Container>::value
,
typename sprout::container_traits<Container>::reference
>::type
range_at_impl(Container& cont, typename sprout::container_traits<Container>::size_type i) {
return *sprout::next(sprout::begin(cont), sprout::range_index_check(cont, i));
}
template<typename Container>
inline SPROUT_CONSTEXPR typename std::enable_if<
@ -661,11 +758,23 @@ namespace sprout {
}
template<typename Container>
inline SPROUT_CONSTEXPR typename std::enable_if<
!sprout::detail::has_mem_at<Container const>::value,
!sprout::detail::has_mem_at<Container const>::value
&& sprout::detail::has_mem_subscript<Container>::value
,
typename sprout::container_traits<Container const>::reference
>::type
range_at_impl(Container const& cont, typename sprout::container_traits<Container const>::size_type i) {
return *sprout::next(sprout::begin(cont), i);
return cont[sprout::range_index_check(cont, i)];
}
template<typename Container>
inline SPROUT_CONSTEXPR typename std::enable_if<
!sprout::detail::has_mem_at<Container const>::value
&& !sprout::detail::has_mem_subscript<Container>::value
,
typename sprout::container_traits<Container const>::reference
>::type
range_at_impl(Container const& cont, typename sprout::container_traits<Container const>::size_type i) {
return *sprout::next(sprout::begin(cont), sprout::range_index_check(cont, i));
}
template<typename T>
@ -949,6 +1058,17 @@ namespace sprout_container_range_detail {
return sprout::detail::range_back_impl(cont);
}
template<typename Container>
inline SPROUT_CONSTEXPR typename sprout::container_traits<Container>::reference
range_subscript_at(Container& cont, typename sprout::container_traits<Container>::size_type i) {
return sprout::detail::range_subscript_at_impl(cont, i);
}
template<typename Container>
inline SPROUT_CONSTEXPR typename sprout::container_traits<Container const>::reference
range_subscript_at(Container const& cont, typename sprout::container_traits<Container const>::size_type i) {
return sprout::detail::range_subscript_at_impl(cont, i);
}
template<typename Container>
inline SPROUT_CONSTEXPR typename sprout::container_traits<Container>::reference
range_at(Container& cont, typename sprout::container_traits<Container>::size_type i) {
@ -1066,6 +1186,18 @@ namespace sprout {
return range_back(cont);
}
static SPROUT_CONSTEXPR typename sprout::container_traits<Container>::reference
range_subscript_at(Container& cont, typename sprout::container_traits<Container>::size_type i) {
using sprout_container_range_detail::range_subscript_at;
using sprout_adl::range_subscript_at;
return range_subscript_at(cont, i);
}
static SPROUT_CONSTEXPR typename sprout::container_traits<Container const>::reference
range_subscript_at(Container const& cont, typename sprout::container_traits<Container const>::size_type i) {
using sprout_container_range_detail::range_subscript_at;
using sprout_adl::range_subscript_at;
return range_subscript_at(cont, i);
}
static SPROUT_CONSTEXPR typename sprout::container_traits<Container>::reference
range_at(Container& cont, typename sprout::container_traits<Container>::size_type i) {
using sprout_container_range_detail::range_at;
using sprout_adl::range_at;
@ -1149,6 +1281,10 @@ namespace sprout {
return sprout::container_range_traits<Container>::range_back(cont);
}
static SPROUT_CONSTEXPR typename sprout::container_traits<Container const>::reference
range_subscript_at(Container const& cont, typename sprout::container_traits<Container const>::size_type i) {
return sprout::container_range_traits<Container>::range_subscript_at(cont, i);
}
static SPROUT_CONSTEXPR typename sprout::container_traits<Container const>::reference
range_at(Container const& cont, typename sprout::container_traits<Container const>::size_type i) {
return sprout::container_range_traits<Container>::range_at(cont, i);
}
@ -1231,6 +1367,14 @@ namespace sprout {
return arr[N - 1];
}
static SPROUT_CONSTEXPR typename sprout::container_traits<T[N]>::reference
range_subscript_at(T (& arr)[N], typename sprout::container_traits<T[N]>::size_type i) {
return arr[i];
}
static SPROUT_CONSTEXPR typename sprout::container_traits<T const[N]>::reference
range_subscript_at(T const (& arr)[N], typename sprout::container_traits<T const[N]>::size_type i) {
return arr[i];
}
static SPROUT_CONSTEXPR typename sprout::container_traits<T[N]>::reference
range_at(T (& arr)[N], typename sprout::container_traits<T[N]>::size_type i) {
return arr[i];
}
@ -1301,6 +1445,10 @@ namespace sprout {
return sprout::container_range_traits<T[N]>::range_back(arr);
}
static SPROUT_CONSTEXPR typename sprout::container_traits<T const[N]>::reference
range_subscript_at(T const (& arr)[N], typename sprout::container_traits<T const[N]>::size_type i) {
return sprout::container_range_traits<T[N]>::range_subscript_at(arr, i);
}
static SPROUT_CONSTEXPR typename sprout::container_traits<T const[N]>::reference
range_at(T const (& arr)[N], typename sprout::container_traits<T const[N]>::size_type i) {
return sprout::container_range_traits<T[N]>::range_at(arr, i);
}
@ -1325,8 +1473,11 @@ namespace sprout {
#include <sprout/container/size.hpp>
#include <sprout/container/front.hpp>
#include <sprout/container/back.hpp>
#include <sprout/container/subscript_at.hpp>
#include <sprout/container/at.hpp>
#include <sprout/container/nth.hpp>
#include <sprout/container/index_of.hpp>
#include <sprout/container/data.hpp>
#include <sprout/container/range_index_check.hpp>
#endif // #ifndef SPROUT_CONTAINER_CONTAINER_RANGE_TRAITS_HPP