diff --git a/sprout/adapt/boost/array.hpp b/sprout/adapt/boost/array.hpp index 7b08fed3..9cbcb0cc 100644 --- a/sprout/adapt/boost/array.hpp +++ b/sprout/adapt/boost/array.hpp @@ -8,7 +8,7 @@ #ifndef SPROUT_ADAPT_BOOST_ARRAY_HPP #define SPROUT_ADAPT_BOOST_ARRAY_HPP -#include +#include #include #include #include diff --git a/sprout/container/at.hpp b/sprout/container/at.hpp index bae01ffe..097ac0ba 100644 --- a/sprout/container/at.hpp +++ b/sprout/container/at.hpp @@ -26,12 +26,14 @@ namespace sprout { // otherwise, Container is not const // && sprout::is_const_cast_convertible // && (callable sprout::as_const(cont).at(i) + // || callable sprout::as_const(cont)[i] // || callable sprout::as_const(cont).begin() // || ADL(without sprout) callable begin(sprout::as_const(cont)) // ) // -> const_cast(sprout::at(sprout::as_const(cont), i)) // otherwise, callable cont.at(i) -> cont.at(i) - // otherwise -> *sprout::next(sprout::begin(cont), i) + // otherwise, callable cont[i] -> cont[sprout::range_index_check(cont, i)] + // otherwise -> *sprout::next(sprout::begin(cont), sprout::range_index_check(cont, i)) // template inline SPROUT_CONSTEXPR typename sprout::container_traits::reference diff --git a/sprout/container/boost/array.hpp b/sprout/container/boost/array.hpp index 846fb1a2..888ce22f 100644 --- a/sprout/container/boost/array.hpp +++ b/sprout/container/boost/array.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -101,13 +102,21 @@ namespace sprout { return cont.elems[N - 1]; } static SPROUT_CONSTEXPR typename sprout::container_traits >::reference - range_at(boost::array& cont, typename sprout::container_traits >::size_type i) { + range_subscript_at(boost::array& cont, typename sprout::container_traits >::size_type i) { return cont.elems[i]; } static SPROUT_CONSTEXPR typename sprout::container_traits const>::reference - range_at(boost::array const& cont, typename sprout::container_traits const>::size_type i) { + range_subscript_at(boost::array const& cont, typename sprout::container_traits const>::size_type i) { return cont.elems[i]; } + static SPROUT_CONSTEXPR typename sprout::container_traits >::reference + range_at(boost::array& cont, typename sprout::container_traits >::size_type i) { + return cont.elems[sprout::range_index_check(cont, i)]; + } + static SPROUT_CONSTEXPR typename sprout::container_traits const>::reference + range_at(boost::array const& cont, typename sprout::container_traits const>::size_type i) { + return cont.elems[sprout::range_index_check(cont, i)]; + } // data access: static SPROUT_CONSTEXPR typename sprout::container_traits >::pointer range_data(boost::array& cont) { diff --git a/sprout/container/container_range_traits.hpp b/sprout/container/container_range_traits.hpp index 21832901..30d03366 100644 --- a/sprout/container/container_range_traits.hpp +++ b/sprout/container/container_range_traits.hpp @@ -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 + struct has_mem_subscript_test { + public: + template< + typename U = T, + typename = typename sprout::identity()[std::declval::size_type>()])>::type + > + static sprout::true_type test(int); + static sprout::false_type test(...); + }; +#if defined(_MSC_VER) && (_MSC_VER > 1900) + template::test(0))>::type> + struct has_mem_subscript + : public Base_ + {}; +#else + template + struct has_mem_subscript + : public sprout::identity::test(0))>::type + {}; +#endif + + template + struct is_substitutable_const_subscript_at + : public sprout::bool_constant< + sprout::is_const_cast_convertible< + typename sprout::container_traits::reference, + typename sprout::container_traits::reference + >::value + && ( + sprout::detail::has_mem_subscript::value + || sprout::detail::has_mem_begin::value + || sprout::detail::has_adl_begin_without_sprout::value + ) + > + {}; + + template + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::detail::is_substitutable_const_subscript_at::value, + typename sprout::container_traits::reference + >::type + range_subscript_at_impl(Container& cont, typename sprout::container_traits::size_type i) { + typedef typename sprout::container_traits::reference type; + return const_cast(sprout::subscript_at(sprout::as_const(cont), i)); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::is_substitutable_const_subscript_at::value + && sprout::detail::has_mem_subscript::value + , + typename sprout::container_traits::reference + >::type + range_subscript_at_impl(Container& cont, typename sprout::container_traits::size_type i) { + return cont[i]; + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::is_substitutable_const_subscript_at::value + && !sprout::detail::has_mem_subscript::value + , + typename sprout::container_traits::reference + >::type + range_subscript_at_impl(Container& cont, typename sprout::container_traits::size_type i) { + return *sprout::next(sprout::begin(cont), i); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::detail::has_mem_subscript::value, + typename sprout::container_traits::reference + >::type + range_subscript_at_impl(Container const& cont, typename sprout::container_traits::size_type i) { + return cont[i]; + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::has_mem_subscript::value, + typename sprout::container_traits::reference + >::type + range_subscript_at_impl(Container const& cont, typename sprout::container_traits::size_type i) { + return *sprout::next(sprout::begin(cont), i); + } + template struct has_mem_at_test { public: @@ -616,6 +700,7 @@ namespace sprout { >::value && ( sprout::detail::has_mem_at::value + || sprout::detail::has_mem_subscript::value || sprout::detail::has_mem_begin::value || sprout::detail::has_adl_begin_without_sprout::value ) @@ -645,11 +730,23 @@ namespace sprout { inline SPROUT_CONSTEXPR typename std::enable_if< !sprout::detail::is_substitutable_const_at::value && !sprout::detail::has_mem_at::value + && sprout::detail::has_mem_subscript::value , typename sprout::container_traits::reference >::type range_at_impl(Container& cont, typename sprout::container_traits::size_type i) { - return *sprout::next(sprout::begin(cont), i); + return cont[sprout::range_index_check(cont, i)]; + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::is_substitutable_const_at::value + && !sprout::detail::has_mem_at::value + && !sprout::detail::has_mem_subscript::value + , + typename sprout::container_traits::reference + >::type + range_at_impl(Container& cont, typename sprout::container_traits::size_type i) { + return *sprout::next(sprout::begin(cont), sprout::range_index_check(cont, i)); } template inline SPROUT_CONSTEXPR typename std::enable_if< @@ -661,11 +758,23 @@ namespace sprout { } template inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_mem_at::value, + !sprout::detail::has_mem_at::value + && sprout::detail::has_mem_subscript::value + , typename sprout::container_traits::reference >::type range_at_impl(Container const& cont, typename sprout::container_traits::size_type i) { - return *sprout::next(sprout::begin(cont), i); + return cont[sprout::range_index_check(cont, i)]; + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::has_mem_at::value + && !sprout::detail::has_mem_subscript::value + , + typename sprout::container_traits::reference + >::type + range_at_impl(Container const& cont, typename sprout::container_traits::size_type i) { + return *sprout::next(sprout::begin(cont), sprout::range_index_check(cont, i)); } template @@ -949,6 +1058,17 @@ namespace sprout_container_range_detail { return sprout::detail::range_back_impl(cont); } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_subscript_at(Container& cont, typename sprout::container_traits::size_type i) { + return sprout::detail::range_subscript_at_impl(cont, i); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_subscript_at(Container const& cont, typename sprout::container_traits::size_type i) { + return sprout::detail::range_subscript_at_impl(cont, i); + } + template inline SPROUT_CONSTEXPR typename sprout::container_traits::reference range_at(Container& cont, typename sprout::container_traits::size_type i) { @@ -1066,6 +1186,18 @@ namespace sprout { return range_back(cont); } static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_subscript_at(Container& cont, typename sprout::container_traits::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::reference + range_subscript_at(Container const& cont, typename sprout::container_traits::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::reference range_at(Container& cont, typename sprout::container_traits::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::range_back(cont); } static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_subscript_at(Container const& cont, typename sprout::container_traits::size_type i) { + return sprout::container_range_traits::range_subscript_at(cont, i); + } + static SPROUT_CONSTEXPR typename sprout::container_traits::reference range_at(Container const& cont, typename sprout::container_traits::size_type i) { return sprout::container_range_traits::range_at(cont, i); } @@ -1231,6 +1367,14 @@ namespace sprout { return arr[N - 1]; } static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_subscript_at(T (& arr)[N], typename sprout::container_traits::size_type i) { + return arr[i]; + } + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_subscript_at(T const (& arr)[N], typename sprout::container_traits::size_type i) { + return arr[i]; + } + static SPROUT_CONSTEXPR typename sprout::container_traits::reference range_at(T (& arr)[N], typename sprout::container_traits::size_type i) { return arr[i]; } @@ -1301,6 +1445,10 @@ namespace sprout { return sprout::container_range_traits::range_back(arr); } static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_subscript_at(T const (& arr)[N], typename sprout::container_traits::size_type i) { + return sprout::container_range_traits::range_subscript_at(arr, i); + } + static SPROUT_CONSTEXPR typename sprout::container_traits::reference range_at(T const (& arr)[N], typename sprout::container_traits::size_type i) { return sprout::container_range_traits::range_at(arr, i); } @@ -1325,8 +1473,11 @@ namespace sprout { #include #include #include +#include +#include #include #include #include +#include #endif // #ifndef SPROUT_CONTAINER_CONTAINER_RANGE_TRAITS_HPP diff --git a/sprout/container/functions.hpp b/sprout/container/functions.hpp index 8b1b024b..ffd956e3 100644 --- a/sprout/container/functions.hpp +++ b/sprout/container/functions.hpp @@ -14,6 +14,5 @@ #include #include #include -#include #endif // #ifndef SPROUT_CONTAINER_FUNCTIONS_HPP diff --git a/sprout/container/range_functions.hpp b/sprout/container/range_functions.hpp index 72649623..1cf65d17 100644 --- a/sprout/container/range_functions.hpp +++ b/sprout/container/range_functions.hpp @@ -20,5 +20,7 @@ #include #include #include +#include +#include #endif // #ifndef SPROUT_CONTAINER_RANGE_FUNCTIONS_HPP diff --git a/sprout/container/range_functions_fwd.hpp b/sprout/container/range_functions_fwd.hpp index 0df5b942..c0e99e9d 100644 --- a/sprout/container/range_functions_fwd.hpp +++ b/sprout/container/range_functions_fwd.hpp @@ -66,6 +66,16 @@ namespace sprout { SPROUT_CONSTEXPR typename sprout::container_traits::reference back(Container const& cont); + // + // subscript_at + // + template + SPROUT_CONSTEXPR typename sprout::container_traits::reference + subscript_at(Container& cont, typename sprout::container_traits::size_type i); + template + SPROUT_CONSTEXPR typename sprout::container_traits::reference + subscript_at(Container const& cont, typename sprout::container_traits::size_type i); + // // at // @@ -105,8 +115,21 @@ namespace sprout { template SPROUT_CONSTEXPR typename sprout::container_traits::pointer data(Container const& cont); -} // namespace sprout + // + // range_index_check + // + template + SPROUT_CONSTEXPR typename sprout::container_traits::size_type + range_index_check(Container const& cont, typename sprout::container_traits::size_type i); + + // + // shrink_to_fit + // + template + SPROUT_CXX14_CONSTEXPR void + shrink_to_fit(Container&& cont); +} // namespace sprout #include #include diff --git a/sprout/container/range_index_check.hpp b/sprout/container/range_index_check.hpp new file mode 100644 index 00000000..57908d87 --- /dev/null +++ b/sprout/container/range_index_check.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_CONTAINER_RANGE_INDEX_CHECK_HPP +#define SPROUT_CONTAINER_RANGE_INDEX_CHECK_HPP + +#include +#include +#include +#include + +namespace sprout { + // + // range_index_check + // + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::size_type + range_index_check(Container const& cont, typename sprout::container_traits::size_type i) { + return i >= sprout::size(cont) ? throw std::out_of_range("range_index_check: index out of range") + : i + ; + } +} // namespace sprout + +#include + +#endif // #ifndef SPROUT_CONTAINER_RANGE_INDEX_CHECK_HPP diff --git a/sprout/container/sscrisk/cel/array.hpp b/sprout/container/sscrisk/cel/array.hpp index de52df87..6419a8f4 100644 --- a/sprout/container/sscrisk/cel/array.hpp +++ b/sprout/container/sscrisk/cel/array.hpp @@ -15,6 +15,7 @@ # include # include # include +# include #endif #if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION @@ -27,8 +28,8 @@ namespace sprout { : public sprout::detail::container_traits_default > { public: - typedef sprout::index_iterator&, true> iterator; - typedef sprout::index_iterator const&, true> const_iterator; + typedef sprout::index_iterator&, true, sprout::detail::const_subscript<> > iterator; + typedef sprout::index_iterator const&, true, sprout::detail::const_subscript<> > const_iterator; }; // diff --git a/sprout/container/std/array.hpp b/sprout/container/std/array.hpp index 4e312940..911ee21b 100644 --- a/sprout/container/std/array.hpp +++ b/sprout/container/std/array.hpp @@ -18,27 +18,9 @@ #include #include #include -#include +#include namespace sprout { - namespace detail { - template - struct const_subscript; - template<> - struct const_subscript - : public sprout::transparent<> - { - public: - template - SPROUT_CONSTEXPR decltype(std::declval()[std::declval()]) - operator()(T&& x, U&& y) - const SPROUT_NOEXCEPT_IF_EXPR(const_cast()[std::declval()])>(sprout::as_const(std::declval())[std::declval()])) - { - return const_cast()[std::declval()])>(sprout::as_const(x)[SPROUT_FORWARD(U, y)]); - } - }; - } // namespace detail - // // container_traits // @@ -60,10 +42,6 @@ namespace sprout { { private: typedef sprout::detail::container_range_traits_default > base_type; - public: - using base_type::range_front; - using base_type::range_back; - using base_type::range_at; public: // iterators: static SPROUT_CONSTEXPR typename sprout::container_traits >::iterator @@ -82,27 +60,7 @@ namespace sprout { range_end(std::array const& cont) { return typename sprout::container_traits const>::iterator(cont, cont.size()); } - // element access: - static SPROUT_CONSTEXPR typename sprout::container_traits >::reference - range_front(std::array& cont) { - typedef typename sprout::container_traits >::reference type; - return const_cast(base_type::range_front(sprout::as_const(cont))); - } - static SPROUT_CONSTEXPR typename sprout::container_traits >::reference - range_back(std::array& cont) { - typedef typename sprout::container_traits >::reference type; - return const_cast(base_type::range_back(sprout::as_const(cont))); - } - static SPROUT_CONSTEXPR typename sprout::container_traits >::reference - range_at(std::array& cont, typename sprout::container_traits >::size_type i) { - typedef typename sprout::container_traits >::reference type; - return const_cast(base_type::range_at(sprout::as_const(cont), i)); - } // data access: - static SPROUT_CONSTEXPR typename sprout::container_traits >::pointer - range_data(std::array& cont) { - return sprout::addressof(range_front(cont)); - } static SPROUT_CONSTEXPR typename sprout::container_traits const>::pointer range_data(std::array const& cont) { return sprout::addressof(range_front(cont)); diff --git a/sprout/container/subscript_at.hpp b/sprout/container/subscript_at.hpp new file mode 100644 index 00000000..4a35d9eb --- /dev/null +++ b/sprout/container/subscript_at.hpp @@ -0,0 +1,74 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_CONTAINER_SUBSCRIPT_AT_HPP +#define SPROUT_CONTAINER_SUBSCRIPT_AT_HPP + +#include +#include +#include +#include + +namespace sprout { + // + // subscript_at + // + // effect: + // sprout::container_range_traits::range_subscript_at(cont, i) + // [default] + // ADL callable range_subscript_at(cont, i) -> range_subscript_at(cont, i) + // [default] + // Container is T[N] -> cont[i] + // otherwise, Container is not const + // && sprout::is_const_cast_convertible + // && (callable sprout::as_const(cont)[i] + // || callable sprout::as_const(cont).begin() + // || ADL(without sprout) callable begin(sprout::as_const(cont)) + // ) + // -> const_cast(sprout::subscript_at(sprout::as_const(cont), i)) + // otherwise, callable cont[i] -> cont[i] + // otherwise -> *sprout::next(sprout::begin(cont), i) + // + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + subscript_at(Container& cont, typename sprout::container_traits::size_type i) { + return sprout::container_range_traits::range_subscript_at(cont, i); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + subscript_at(Container const& cont, typename sprout::container_traits::size_type i) { + return sprout::container_range_traits::range_subscript_at(cont, i); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + subscript_at(T (& arr)[N], typename sprout::container_traits::size_type i) { + return sprout::container_range_traits::range_subscript_at(arr, i); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + subscript_at(T const (& arr)[N], typename sprout::container_traits::size_type i) { + return sprout::container_range_traits::range_subscript_at(arr, i); + } + + // + // csubscript_at + // + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + csubscript_at(Container const& cont, typename sprout::container_traits::size_type i) { + return sprout::subscript_at(cont, i); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + csubscript_at(T const (& arr)[N], typename sprout::container_traits::size_type i) { + return sprout::subscript_at(arr, i); + } +} // namespace sprout + +#include + +#endif // #ifndef SPROUT_CONTAINER_SUBSCRIPT_AT_HPP diff --git a/sprout/detail/functional/const_subscript.hpp b/sprout/detail/functional/const_subscript.hpp new file mode 100644 index 00000000..ee71dd95 --- /dev/null +++ b/sprout/detail/functional/const_subscript.hpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_DETAIL_FUNCTIONAL_CONST_SUBSCRIPT_HPP +#define SPROUT_DETAIL_FUNCTIONAL_CONST_SUBSCRIPT_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + struct const_subscript; + template<> + struct const_subscript + : public sprout::transparent<> + { + public: + template + SPROUT_CONSTEXPR decltype(std::declval()[std::declval()]) + operator()(T&& x, U&& y) + const SPROUT_NOEXCEPT_IF_EXPR(const_cast()[std::declval()])>(sprout::as_const(std::declval())[std::declval()])) + { + return const_cast()[std::declval()])>(sprout::as_const(x)[SPROUT_FORWARD(U, y)]); + } + }; + } // namespace detail +} // namespace sprout + +#endif // #ifndef SPROUT_DETAIL_FUNCTIONAL_CONST_SUBSCRIPT_HPP