From 909ccfe73a6a1866c2d8f7e4fa6e6736b4d94815 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Sat, 12 Jul 2014 18:04:45 +0900 Subject: [PATCH] add front, back, at : container access non-member functions --- sprout/container/at.hpp | 87 ++++++ sprout/container/back.hpp | 87 ++++++ sprout/container/container_range_traits.hpp | 283 +++++++++++++++++++- sprout/container/front.hpp | 87 ++++++ sprout/container/range_functions.hpp | 3 + sprout/container/range_functions_fwd.hpp | 42 ++- 6 files changed, 572 insertions(+), 17 deletions(-) create mode 100644 sprout/container/at.hpp create mode 100644 sprout/container/back.hpp create mode 100644 sprout/container/front.hpp diff --git a/sprout/container/at.hpp b/sprout/container/at.hpp new file mode 100644 index 00000000..99d6edb7 --- /dev/null +++ b/sprout/container/at.hpp @@ -0,0 +1,87 @@ +/*============================================================================= + Copyright (c) 2011-2014 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_AT_HPP +#define SPROUT_CONTAINER_AT_HPP + +#include +#include +#include +#include +#include + +namespace sprout_adl { + sprout::not_found_via_adl range_at(...); +} // namespace sprout_adl + +namespace sprout { + namespace container_detail { + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_at(Container& cont, typename sprout::container_traits::size_type i) { + return sprout::container_range_traits::range_at(cont, i); + } + template + inline 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); + } + } // namespace container_detail + + // + // at + // + // effect: + // ADL callable range_at(cont, i) -> range_at(cont, i) + // otherwise -> sprout::container_range_traits::range_at(cont, i) + // [default] + // callable cont.at(i) -> cont.at(i) + // otherwise -> *next(begin(cont), i) + // + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + at(Container& cont, typename sprout::container_traits::size_type i) { + using sprout::container_detail::range_at; + using sprout_adl::range_at; + return range_at(cont, i); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + at(Container const& cont, typename sprout::container_traits::size_type i) { + using sprout::container_detail::range_at; + using sprout_adl::range_at; + return range_at(cont, i); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + at(T (& arr)[N], typename sprout::container_traits::size_type i) { + return sprout::container_detail::range_at(arr, i); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + at(T const (& arr)[N], typename sprout::container_traits::size_type i) { + return sprout::container_detail::range_at(arr, i); + } + + // + // cat + // + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + cat(Container const& cont, typename sprout::container_traits::size_type i) { + return sprout::at(cont, i); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + cat(T const (& arr)[N], typename sprout::container_traits::size_type i) { + return sprout::at(arr, i); + } +} // namespace sprout + +#include + +#endif // #ifndef SPROUT_CONTAINER_AT_HPP diff --git a/sprout/container/back.hpp b/sprout/container/back.hpp new file mode 100644 index 00000000..a73921f6 --- /dev/null +++ b/sprout/container/back.hpp @@ -0,0 +1,87 @@ +/*============================================================================= + Copyright (c) 2011-2014 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_BACK_HPP +#define SPROUT_CONTAINER_BACK_HPP + +#include +#include +#include +#include +#include + +namespace sprout_adl { + sprout::not_found_via_adl range_back(...); +} // namespace sprout_adl + +namespace sprout { + namespace container_detail { + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_back(Container& cont) { + return sprout::container_range_traits::range_back(cont); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_back(Container const& cont) { + return sprout::container_range_traits::range_back(cont); + } + } // namespace container_detail + + // + // back + // + // effect: + // ADL callable range_back(cont) -> range_back(cont) + // otherwise -> sprout::container_range_traits::range_back(cont) + // [default] + // callable cont.back() -> cont.back() + // otherwise -> *prev(end(cont)) + // + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + back(Container& cont) { + using sprout::container_detail::range_back; + using sprout_adl::range_back; + return range_back(cont); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + back(Container const& cont) { + using sprout::container_detail::range_back; + using sprout_adl::range_back; + return range_back(cont); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + back(T (& arr)[N]) { + return sprout::container_detail::range_back(arr); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + back(T const (& arr)[N]) { + return sprout::container_detail::range_back(arr); + } + + // + // cback + // + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + cback(Container const& cont) { + return sprout::back(cont); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + cback(T const (& arr)[N]) { + return sprout::back(arr); + } +} // namespace sprout + +#include + +#endif // #ifndef SPROUT_CONTAINER_BACK_HPP diff --git a/sprout/container/container_range_traits.hpp b/sprout/container/container_range_traits.hpp index 8d4ab805..48b04a67 100644 --- a/sprout/container/container_range_traits.hpp +++ b/sprout/container/container_range_traits.hpp @@ -53,7 +53,7 @@ namespace sprout { template struct container_range_traits_range_size_impl< Container, - typename std::enable_if::value>::type + typename std::enable_if::value>::type > { public: static SPROUT_CONSTEXPR typename sprout::container_traits::size_type @@ -64,7 +64,7 @@ namespace sprout { template struct container_range_traits_range_size_impl< Container, - typename std::enable_if::value>::type + typename std::enable_if::value>::type > { public: static SPROUT_CONSTEXPR typename sprout::container_traits::size_type @@ -100,7 +100,7 @@ namespace sprout { template struct container_range_traits_range_empty_impl< Container, - typename std::enable_if::value>::type + typename std::enable_if::value>::type > { public: static SPROUT_CONSTEXPR bool @@ -111,7 +111,7 @@ namespace sprout { template struct container_range_traits_range_empty_impl< Container, - typename std::enable_if::value>::type + typename std::enable_if::value>::type > { public: static SPROUT_CONSTEXPR bool @@ -119,12 +119,234 @@ namespace sprout { return sprout::size(cont) == 0; } }; + + template + struct has_mem_front_test { + public: + template< + typename U = T, + typename = typename sprout::identity().front())>::type + > + static sprout::true_type test(int); + static sprout::false_type test(...); + }; +#if defined(_MSC_VER) + template::test(0))>::type> + struct has_mem_front + : public Base_ + {}; +#else + template + struct has_mem_front + : public sprout::identity::test(0))>::type + {}; +#endif + + template + struct container_range_traits_range_front_impl; + template + struct container_range_traits_range_front_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_front(Container& cont) { + return cont.front(); + } + }; + template + struct container_range_traits_range_front_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_front(Container& cont) { + return *sprout::begin(cont); + } + }; + + template + struct container_range_traits_range_front_const_impl; + template + struct container_range_traits_range_front_const_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_front(Container const& cont) { + return cont.front(); + } + }; + template + struct container_range_traits_range_front_const_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_front(Container const& cont) { + return *sprout::begin(cont); + } + }; + + template + struct has_mem_back_test { + public: + template< + typename U = T, + typename = typename sprout::identity().back())>::type + > + static sprout::true_type test(int); + static sprout::false_type test(...); + }; +#if defined(_MSC_VER) + template::test(0))>::type> + struct has_mem_back + : public Base_ + {}; +#else + template + struct has_mem_back + : public sprout::identity::test(0))>::type + {}; +#endif + + template + struct container_range_traits_range_back_impl; + template + struct container_range_traits_range_back_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_back(Container& cont) { + return cont.back(); + } + }; + template + struct container_range_traits_range_back_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_back(Container& cont) { + return *sprout::prev(sprout::end(cont)); + } + }; + + template + struct container_range_traits_range_back_const_impl; + template + struct container_range_traits_range_back_const_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_back(Container const& cont) { + return cont.back(); + } + }; + template + struct container_range_traits_range_back_const_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_back(Container const& cont) { + return *sprout::prev(sprout::end(cont)); + } + }; + + template + struct has_mem_at_test { + public: + template< + typename U = T, + typename = typename sprout::identity().at(std::declval::size_type>()))>::type + > + static sprout::true_type test(int); + static sprout::false_type test(...); + }; +#if defined(_MSC_VER) + template::test(0))>::type> + struct has_mem_at + : public Base_ + {}; +#else + template + struct has_mem_at + : public sprout::identity::test(0))>::type + {}; +#endif + + template + struct container_range_traits_range_at_impl; + template + struct container_range_traits_range_at_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_at(Container& cont, typename sprout::container_traits::size_type i) { + return cont.at(i); + } + }; + template + struct container_range_traits_range_at_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_at(Container& cont, typename sprout::container_traits::size_type i) { + return *sprout::next(sprout::begin(cont), i); + } + }; + + template + struct container_range_traits_range_at_const_impl; + template + struct container_range_traits_range_at_const_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_at(Container const& cont, typename sprout::container_traits::size_type i) { + return cont.at(i); + } + }; + template + struct container_range_traits_range_at_const_impl< + Container, + typename std::enable_if::value>::type + > { + public: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_at(Container const& cont, typename sprout::container_traits::size_type i) { + return *sprout::next(sprout::begin(cont), i); + } + }; } // namespace detail template struct container_range_traits : public sprout::detail::container_range_traits_range_size_impl , public sprout::detail::container_range_traits_range_empty_impl + , public sprout::detail::container_range_traits_range_front_impl + , public sprout::detail::container_range_traits_range_front_const_impl + , public sprout::detail::container_range_traits_range_back_impl + , public sprout::detail::container_range_traits_range_back_const_impl + , public sprout::detail::container_range_traits_range_at_impl + , public sprout::detail::container_range_traits_range_at_const_impl { public: // iterators: @@ -166,6 +388,19 @@ namespace sprout { range_empty(Container const& cont) { return sprout::container_range_traits::range_empty(cont); } + // element access: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_front(Container const& cont) { + return sprout::container_range_traits::range_front(cont); + } + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_back(Container const& cont) { + return sprout::container_range_traits::range_back(cont); + } + 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); + } }; template @@ -201,6 +436,31 @@ namespace sprout { range_empty(T const (&)[N]) { return false; } + // element access: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_front(T (& arr)[N]) { + return arr[0]; + } + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_front(T const (& arr)[N]) { + return arr[0]; + } + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_back(T (& arr)[N]) { + return arr[N - 1]; + } + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_back(T const (& arr)[N]) { + return arr[N - 1]; + } + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_at(T (& arr)[N], typename sprout::container_traits::size_type i) { + return arr[i]; + } + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_at(T const (& arr)[N], typename sprout::container_traits::size_type i) { + return arr[i]; + } }; template struct container_range_traits { @@ -210,7 +470,7 @@ namespace sprout { range_begin(T const (& arr)[N]) { return sprout::container_range_traits::range_begin(arr); } - static SPROUT_CONSTEXPR typename sprout::container_traits::const_iterator + static SPROUT_CONSTEXPR typename sprout::container_traits::iterator range_end(T const (& arr)[N]) { return sprout::container_range_traits::range_end(arr); } @@ -223,6 +483,19 @@ namespace sprout { range_empty(T const (& arr)[N]) { return sprout::container_range_traits::range_empty(arr); } + // element access: + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_front(T const (& arr)[N]) { + return sprout::container_range_traits::range_front(arr); + } + static SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_back(T const (& arr)[N]) { + return sprout::container_range_traits::range_back(arr); + } + 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); + } }; } // namespace sprout diff --git a/sprout/container/front.hpp b/sprout/container/front.hpp new file mode 100644 index 00000000..c87ccbae --- /dev/null +++ b/sprout/container/front.hpp @@ -0,0 +1,87 @@ +/*============================================================================= + Copyright (c) 2011-2014 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_FRONT_HPP +#define SPROUT_CONTAINER_FRONT_HPP + +#include +#include +#include +#include +#include + +namespace sprout_adl { + sprout::not_found_via_adl range_front(...); +} // namespace sprout_adl + +namespace sprout { + namespace container_detail { + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_front(Container& cont) { + return sprout::container_range_traits::range_front(cont); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + range_front(Container const& cont) { + return sprout::container_range_traits::range_front(cont); + } + } // namespace container_detail + + // + // front + // + // effect: + // ADL callable range_front(cont) -> range_front(cont) + // otherwise -> sprout::container_range_traits::range_front(cont) + // [default] + // callable cont.front() -> cont.front() + // otherwise -> *begin(cont) + // + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + front(Container& cont) { + using sprout::container_detail::range_front; + using sprout_adl::range_front; + return range_front(cont); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + front(Container const& cont) { + using sprout::container_detail::range_front; + using sprout_adl::range_front; + return range_front(cont); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + front(T (& arr)[N]) { + return sprout::container_detail::range_front(arr); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + front(T const (& arr)[N]) { + return sprout::container_detail::range_front(arr); + } + + // + // cfront + // + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + cfront(Container const& cont) { + return sprout::front(cont); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::reference + cfront(T const (& arr)[N]) { + return sprout::front(arr); + } +} // namespace sprout + +#include + +#endif // #ifndef SPROUT_CONTAINER_FRONT_HPP diff --git a/sprout/container/range_functions.hpp b/sprout/container/range_functions.hpp index d0c3900d..a4e594a4 100644 --- a/sprout/container/range_functions.hpp +++ b/sprout/container/range_functions.hpp @@ -14,5 +14,8 @@ #include #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 c8f61a63..44b1da03 100644 --- a/sprout/container/range_functions_fwd.hpp +++ b/sprout/container/range_functions_fwd.hpp @@ -21,12 +21,6 @@ namespace sprout { template SPROUT_CONSTEXPR typename sprout::container_traits::iterator begin(Container const& cont); - // - // cbegin - // - template - inline SPROUT_CONSTEXPR typename sprout::container_traits::iterator - cbegin(Container const& cont); // // end @@ -37,12 +31,6 @@ namespace sprout { template SPROUT_CONSTEXPR typename sprout::container_traits::iterator end(Container const& cont); - // - // cend - // - template - inline SPROUT_CONSTEXPR typename sprout::container_traits::iterator - cend(Container const& cont); // // size @@ -57,6 +45,36 @@ namespace sprout { template SPROUT_CONSTEXPR bool empty(Container const& cont); + + // + // front + // + template + SPROUT_CONSTEXPR typename sprout::container_traits::reference + front(Container& cont); + template + SPROUT_CONSTEXPR typename sprout::container_traits::reference + front(Container const& cont); + + // + // back + // + template + SPROUT_CONSTEXPR typename sprout::container_traits::reference + back(Container& cont); + template + SPROUT_CONSTEXPR typename sprout::container_traits::reference + back(Container const& cont); + + // + // at + // + template + SPROUT_CONSTEXPR typename sprout::container_traits::reference + at(Container& cont, typename sprout::container_traits::size_type i); + template + SPROUT_CONSTEXPR typename sprout::container_traits::reference + at(Container const& cont, typename sprout::container_traits::size_type i); } // namespace sprout