From 8278a2642c6d91728cc536141bf5db37debbbfe3 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Sun, 17 Apr 2016 16:11:43 +0900 Subject: [PATCH] change range functions adapt --- sprout/array/array.hpp | 41 -- sprout/container/at.hpp | 7 + sprout/container/back.hpp | 7 + sprout/container/begin.hpp | 10 +- sprout/container/container_range_traits.hpp | 350 +++++++++++++++--- sprout/container/data.hpp | 4 + sprout/container/end.hpp | 10 +- sprout/container/front.hpp | 7 + sprout/container/index_of.hpp | 9 +- sprout/container/nth.hpp | 7 + sprout/iterator/const_iterator_cast.hpp | 8 +- .../type_traits/is_const_cast_convertible.hpp | 43 +++ sprout/type_traits/relationship.hpp | 1 + testspr/tools.hpp | 1 + testspr/utility.hpp | 49 +++ 15 files changed, 454 insertions(+), 100 deletions(-) create mode 100644 sprout/type_traits/is_const_cast_convertible.hpp create mode 100644 testspr/utility.hpp diff --git a/sprout/array/array.hpp b/sprout/array/array.hpp index bd944814..024e3901 100644 --- a/sprout/array/array.hpp +++ b/sprout/array/array.hpp @@ -282,47 +282,6 @@ namespace sprout { lhs.swap(rhs); } - template - inline SPROUT_CONSTEXPR typename sprout::array::iterator - range_begin(sprout::array& t) SPROUT_NOEXCEPT { - return sprout::const_iterator_cast::iterator>(sprout::as_const(t).begin()); - } - template - inline SPROUT_CONSTEXPR typename sprout::array::iterator - range_end(sprout::array& t) SPROUT_NOEXCEPT { - return sprout::const_iterator_cast::iterator>(sprout::as_const(t).end()); - } - template - inline SPROUT_CONSTEXPR typename sprout::array::reference - range_at(sprout::array& t, typename sprout::array::size_type i) { - return const_cast::reference>(sprout::as_const(t).at(i)); - } - template - inline SPROUT_CONSTEXPR typename sprout::array::reference - range_front(sprout::array& t) { - return const_cast::reference>(sprout::as_const(t).front()); - } - template - inline SPROUT_CONSTEXPR typename sprout::array::reference - range_back(sprout::array& t) { - return const_cast::reference>(sprout::as_const(t).back()); - } - template - inline SPROUT_CONSTEXPR typename sprout::array::iterator - range_nth(sprout::array& t, typename sprout::array::size_type i) { - return sprout::const_iterator_cast::iterator>(sprout::as_const(t).nth(i)); - } - template - inline SPROUT_CONSTEXPR typename sprout::array::size_type - range_index_of(sprout::array& t, typename sprout::array::iterator p) SPROUT_NOEXCEPT { - return sprout::as_const(t).index_of(p); - } - template - inline SPROUT_CONSTEXPR typename sprout::array::pointer - range_data(sprout::array& t) SPROUT_NOEXCEPT { - return const_cast::pointer>(sprout::as_const(t).data()); - } - // // to_array // diff --git a/sprout/container/at.hpp b/sprout/container/at.hpp index 4eb273b1..bae01ffe 100644 --- a/sprout/container/at.hpp +++ b/sprout/container/at.hpp @@ -23,6 +23,13 @@ namespace sprout { // ADL callable range_at(cont, i) -> range_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).at(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) // diff --git a/sprout/container/back.hpp b/sprout/container/back.hpp index dc7da091..30fb9ab4 100644 --- a/sprout/container/back.hpp +++ b/sprout/container/back.hpp @@ -23,6 +23,13 @@ namespace sprout { // ADL callable range_back(cont) -> range_back(cont) // [default] // Container is T[N] -> cont[N - 1] + // otherwise, Container is not const + // && sprout::is_const_cast_convertible + // && (callable sprout::as_const(cont).back() + // || callable sprout::as_const(cont).begin() + // || ADL(without sprout) callable begin(sprout::as_const(cont)) + // ) + // -> const_cast(sprout::back(sprout::as_const(cont))) // otherwise, callable cont.back() -> cont.back() // otherwise -> *sprout::next(sprout::begin(cont), sprout::size(cont) - 1) // diff --git a/sprout/container/begin.hpp b/sprout/container/begin.hpp index 66d9083b..1c968e8b 100644 --- a/sprout/container/begin.hpp +++ b/sprout/container/begin.hpp @@ -23,8 +23,14 @@ namespace sprout { // ADL callable range_begin(cont) -> range_begin(cont) // [default] // Container is T[N] -> iterator(cont) - // otherwise, ADL callable begin(cont) -> begin(cont) - // otherwise, callabe cont.begin() -> cont.begin() + // otherwise, Container is not const + // && sprout::is_const_iterator_cast_convertible + // && (callable sprout::as_const(cont).begin() + // || ADL(without sprout) callable begin(sprout::as_const(cont)) + // ) + // -> sprout::const_iterator_cast(sprout::begin(sprout::as_const(cont))) + // otherwise, callable cont.begin() -> cont.begin() + // otherwise, ADL(without sprout) callable begin(cont) -> begin(cont) // otherwise -> std::begin(cont) // template diff --git a/sprout/container/container_range_traits.hpp b/sprout/container/container_range_traits.hpp index fc88e1ca..21832901 100644 --- a/sprout/container/container_range_traits.hpp +++ b/sprout/container/container_range_traits.hpp @@ -15,11 +15,14 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include namespace sprout_adl { @@ -132,30 +135,34 @@ namespace sprout { {}; #endif - template - inline SPROUT_CONSTEXPR typename sprout::container_traits::iterator - range_adl_begin(Container& cont) { - using std::begin; - return begin(cont); - } - template - inline SPROUT_CONSTEXPR typename sprout::container_traits::iterator - range_adl_begin(Container const& cont) { - using std::begin; - return begin(cont); - } + template + struct is_substitutable_const_begin + : public sprout::bool_constant< + sprout::is_const_iterator_cast_convertible< + typename sprout::container_traits::iterator, + typename sprout::container_traits::iterator + >::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::has_adl_begin_without_sprout::value, + sprout::detail::is_substitutable_const_begin::value, typename sprout::container_traits::iterator >::type range_begin_impl(Container& cont) { - return sprout_container_range_detail::range_adl_begin(cont); + typedef typename sprout::container_traits::iterator type; + return sprout::const_iterator_cast(sprout::begin(sprout::as_const(cont))); } template inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_adl_begin_without_sprout::value && sprout::detail::has_mem_begin::value, + !sprout::detail::is_substitutable_const_begin::value + && sprout::detail::has_mem_begin::value + , typename sprout::container_traits::iterator >::type range_begin_impl(Container& cont) { @@ -163,7 +170,21 @@ namespace sprout { } template inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_adl_begin_without_sprout::value && !sprout::detail::has_mem_begin::value, + !sprout::detail::is_substitutable_const_begin::value + && !sprout::detail::has_mem_begin::value + && sprout::detail::has_adl_begin_without_sprout::value + , + typename sprout::container_traits::iterator + >::type + range_begin_impl(Container& cont) { + return sprout_container_range_detail::range_adl_begin(cont); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::is_substitutable_const_begin::value + && !sprout::detail::has_mem_begin::value + && !sprout::detail::has_adl_begin_without_sprout::value + , typename sprout::container_traits::iterator >::type range_begin_impl(Container& cont) { @@ -171,15 +192,7 @@ namespace sprout { } template inline SPROUT_CONSTEXPR typename std::enable_if< - sprout::detail::has_adl_begin_without_sprout::value, - typename sprout::container_traits::iterator - >::type - range_begin_impl(Container const& cont) { - return sprout_container_range_detail::range_adl_begin(cont); - } - template - inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_adl_begin_without_sprout::value && sprout::detail::has_mem_begin::value, + sprout::detail::has_mem_begin::value, typename sprout::container_traits::iterator >::type range_begin_impl(Container const& cont) { @@ -187,7 +200,19 @@ namespace sprout { } template inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_adl_begin_without_sprout::value && !sprout::detail::has_mem_begin::value, + !sprout::detail::has_mem_begin::value + && sprout::detail::has_adl_begin_without_sprout::value + , + typename sprout::container_traits::iterator + >::type + range_begin_impl(Container const& cont) { + return sprout_container_range_detail::range_adl_begin(cont); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::has_mem_begin::value + && !sprout::detail::has_adl_begin_without_sprout::value + , typename sprout::container_traits::iterator >::type range_begin_impl(Container const& cont) { @@ -236,22 +261,34 @@ namespace sprout { {}; #endif - template - inline SPROUT_CONSTEXPR typename sprout::container_traits::iterator - range_adl_end(Container& cont) { - using std::end; - return end(cont); - } - template - inline SPROUT_CONSTEXPR typename sprout::container_traits::iterator - range_adl_end(Container const& cont) { - using std::end; - return end(cont); - } + template + struct is_substitutable_const_end + : public sprout::bool_constant< + sprout::is_const_iterator_cast_convertible< + typename sprout::container_traits::iterator, + typename sprout::container_traits::iterator + >::value + && ( + sprout::detail::has_mem_end::value + || sprout::detail::has_adl_end_without_sprout::value + ) + > + {}; template inline SPROUT_CONSTEXPR typename std::enable_if< - sprout::detail::has_adl_end_without_sprout::value, + sprout::detail::is_substitutable_const_end::value, + typename sprout::container_traits::iterator + >::type + range_end_impl(Container& cont) { + typedef typename sprout::container_traits::iterator type; + return sprout::const_iterator_cast(sprout::end(sprout::as_const(cont))); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::is_substitutable_const_end::value + && sprout::detail::has_adl_end_without_sprout::value + , typename sprout::container_traits::iterator >::type range_end_impl(Container& cont) { @@ -259,7 +296,10 @@ namespace sprout { } template inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_adl_end_without_sprout::value && sprout::detail::has_mem_end::value, + !sprout::detail::is_substitutable_const_end::value + && !sprout::detail::has_adl_end_without_sprout::value + && sprout::detail::has_mem_end::value + , typename sprout::container_traits::iterator >::type range_end_impl(Container& cont) { @@ -267,7 +307,10 @@ namespace sprout { } template inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_adl_end_without_sprout::value && !sprout::detail::has_mem_end::value, + !sprout::detail::is_substitutable_const_end::value + && !sprout::detail::has_adl_end_without_sprout::value + && !sprout::detail::has_mem_end::value + , typename sprout::container_traits::iterator >::type range_end_impl(Container& cont) { @@ -398,9 +441,35 @@ namespace sprout { {}; #endif + template + struct is_substitutable_const_front + : public sprout::bool_constant< + sprout::is_const_cast_convertible< + typename sprout::container_traits::reference, + typename sprout::container_traits::reference + >::value + && ( + sprout::detail::has_mem_front::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::has_mem_front::value, + sprout::detail::is_substitutable_const_front::value, + typename sprout::container_traits::reference + >::type + range_front_impl(Container& cont) { + typedef typename sprout::container_traits::reference type; + return const_cast(sprout::front(sprout::as_const(cont))); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::is_substitutable_const_front::value + && sprout::detail::has_mem_front::value + , typename sprout::container_traits::reference >::type range_front_impl(Container& cont) { @@ -408,7 +477,9 @@ namespace sprout { } template inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_mem_front::value, + !sprout::detail::is_substitutable_const_front::value + && !sprout::detail::has_mem_front::value + , typename sprout::container_traits::reference >::type range_front_impl(Container& cont) { @@ -453,9 +524,35 @@ namespace sprout { {}; #endif + template + struct is_substitutable_const_back + : public sprout::bool_constant< + sprout::is_const_cast_convertible< + typename sprout::container_traits::reference, + typename sprout::container_traits::reference + >::value + && ( + sprout::detail::has_mem_back::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::has_mem_back::value, + sprout::detail::is_substitutable_const_back::value, + typename sprout::container_traits::reference + >::type + range_back_impl(Container& cont) { + typedef typename sprout::container_traits::reference type; + return const_cast(sprout::back(sprout::as_const(cont))); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::is_substitutable_const_back::value + && sprout::detail::has_mem_back::value + , typename sprout::container_traits::reference >::type range_back_impl(Container& cont) { @@ -463,7 +560,9 @@ namespace sprout { } template inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_mem_back::value, + !sprout::detail::is_substitutable_const_back::value + && !sprout::detail::has_mem_back::value + , typename sprout::container_traits::reference >::type range_back_impl(Container& cont) { @@ -508,9 +607,35 @@ namespace sprout { {}; #endif + template + struct is_substitutable_const_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_at::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::has_mem_at::value, + sprout::detail::is_substitutable_const_at::value, + typename sprout::container_traits::reference + >::type + range_at_impl(Container& cont, typename sprout::container_traits::size_type i) { + typedef typename sprout::container_traits::reference type; + return const_cast(sprout::at(sprout::as_const(cont), i)); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::is_substitutable_const_at::value + && sprout::detail::has_mem_at::value + , typename sprout::container_traits::reference >::type range_at_impl(Container& cont, typename sprout::container_traits::size_type i) { @@ -518,7 +643,9 @@ namespace sprout { } template inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_mem_at::value, + !sprout::detail::is_substitutable_const_at::value + && !sprout::detail::has_mem_at::value + , typename sprout::container_traits::reference >::type range_at_impl(Container& cont, typename sprout::container_traits::size_type i) { @@ -563,9 +690,35 @@ namespace sprout { {}; #endif + template + struct is_substitutable_const_nth + : public sprout::bool_constant< + sprout::is_const_iterator_cast_convertible< + typename sprout::container_traits::iterator, + typename sprout::container_traits::iterator + >::value + && ( + sprout::detail::has_mem_nth::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::has_mem_nth::value, + sprout::detail::is_substitutable_const_nth::value, + typename sprout::container_traits::iterator + >::type + range_nth_impl(Container& cont, typename sprout::container_traits::size_type i) { + typedef typename sprout::container_traits::iterator type; + return sprout::const_iterator_cast(sprout::nth(sprout::as_const(cont), i)); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::is_substitutable_const_nth::value + && sprout::detail::has_mem_nth::value + , typename sprout::container_traits::iterator >::type range_nth_impl(Container& cont, typename sprout::container_traits::size_type i) { @@ -573,7 +726,9 @@ namespace sprout { } template inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_mem_nth::value, + !sprout::detail::is_substitutable_const_nth::value + && !sprout::detail::has_mem_nth::value + , typename sprout::container_traits::iterator >::type range_nth_impl(Container& cont, typename sprout::container_traits::size_type i) { @@ -618,9 +773,35 @@ namespace sprout { {}; #endif + template + struct is_substitutable_const_index_of + : public sprout::bool_constant< + sprout::is_const_iterator_cast_convertible< + typename sprout::container_traits::iterator, + typename sprout::container_traits::iterator + >::value + && ( + sprout::detail::has_mem_index_of::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::has_mem_index_of::value, + sprout::detail::is_substitutable_const_index_of::value, + typename sprout::container_traits::size_type + >::type + range_index_of_impl(Container& cont, typename sprout::container_traits::iterator p) { + typedef typename sprout::container_traits::iterator type; + return sprout::index_of(sprout::as_const(cont), sprout::const_iterator_cast(p)); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::is_substitutable_const_index_of::value + && sprout::detail::has_mem_index_of::value + , typename sprout::container_traits::size_type >::type range_index_of_impl(Container& cont, typename sprout::container_traits::iterator p) { @@ -628,7 +809,9 @@ namespace sprout { } template inline SPROUT_CONSTEXPR typename std::enable_if< - !sprout::detail::has_mem_index_of::value, + !sprout::detail::is_substitutable_const_index_of::value + && !sprout::detail::has_mem_index_of::value + , typename sprout::container_traits::size_type >::type range_index_of_impl(Container& cont, typename sprout::container_traits::iterator p) { @@ -650,6 +833,62 @@ namespace sprout { range_index_of_impl(Container const& cont, typename sprout::container_traits::iterator p) { return sprout::distance(sprout::begin(cont), p); } + + template + struct has_mem_data_test { + public: + template< + typename U = T, + typename = typename sprout::identity().data())>::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_data + : public Base_ + {}; +#else + template + struct has_mem_data + : public sprout::identity::test(0))>::type + {}; +#endif + + template + struct is_substitutable_const_data + : public sprout::bool_constant< + sprout::is_const_cast_convertible< + typename sprout::container_traits::pointer, + typename sprout::container_traits::pointer + >::value + && sprout::detail::has_mem_data::value + > + {}; + + template + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::detail::is_substitutable_const_data::value, + typename sprout::container_traits::pointer + >::type + range_data_impl(Container& cont) { + typedef typename sprout::container_traits::pointer type; + return const_cast(sprout::data(sprout::as_const(cont))); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + !sprout::detail::is_substitutable_const_data::value, + typename sprout::container_traits::pointer + >::type + range_data_impl(Container& cont) { + return cont.data(); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::pointer + range_data_impl(Container const& cont) { + return cont.data(); + } } // namespace detail } // namespace sprout @@ -746,12 +985,12 @@ namespace sprout_container_range_detail { template inline SPROUT_CONSTEXPR typename sprout::container_traits::pointer range_data(Container& cont) { - return cont.data(); + return sprout::detail::range_data_impl(cont); } template inline SPROUT_CONSTEXPR typename sprout::container_traits::pointer range_data(Container const& cont) { - return cont.data(); + return sprout::detail::range_data_impl(cont); } } // namespace sprout_container_range_detail @@ -1084,5 +1323,10 @@ namespace sprout { #include #include #include +#include +#include +#include +#include +#include #endif // #ifndef SPROUT_CONTAINER_CONTAINER_RANGE_TRAITS_HPP diff --git a/sprout/container/data.hpp b/sprout/container/data.hpp index f9b59423..389a33b4 100644 --- a/sprout/container/data.hpp +++ b/sprout/container/data.hpp @@ -23,6 +23,10 @@ namespace sprout { // ADL callable range_data(cont) -> range_data(cont) // [default] // Container is T[N] -> pointer(cont) + // otherwise, Container is not const + // && sprout::is_const_cast_convertible + // && callable sprout::as_const(cont).data() + // -> const_cast(sprout::data(sprout::as_const(cont))) // cont.data() // template diff --git a/sprout/container/end.hpp b/sprout/container/end.hpp index 13addd04..7b1f7fe8 100644 --- a/sprout/container/end.hpp +++ b/sprout/container/end.hpp @@ -23,8 +23,14 @@ namespace sprout { // ADL callable range_end(cont) -> range_end(cont) // [default] // Container is T[N] -> iterator(cont) - // otherwise, ADL callable end(cont) -> end(cont) - // otherwise, callabe cont.end() -> cont.end() + // otherwise, Container is not const + // && sprout::is_const_iterator_cast_convertible + // && (callable sprout::as_const(cont).end() + // || ADL(without sprout) callable end(sprout::as_const(cont)) + // ) + // -> sprout::const_iterator_cast(sprout::end(sprout::as_const(cont))) + // otherwise, callable cont.end() -> cont.end() + // otherwise, ADL(without sprout) callable end(cont) -> end(cont) // otherwise -> std::end(cont) // template diff --git a/sprout/container/front.hpp b/sprout/container/front.hpp index 338e662e..aba44046 100644 --- a/sprout/container/front.hpp +++ b/sprout/container/front.hpp @@ -23,6 +23,13 @@ namespace sprout { // ADL callable range_front(cont) -> range_front(cont) // [default] // Container is T[N] -> cont[0] + // otherwise, Container is not const + // && sprout::is_const_cast_convertible + // && (callable sprout::as_const(cont).front() + // || callable sprout::as_const(cont).begin() + // || ADL(without sprout) callable begin(sprout::as_const(cont)) + // ) + // -> const_cast(sprout::front(sprout::as_const(cont))) // otherwise, callable cont.front() -> cont.front() // otherwise -> *sprout::begin(cont) // diff --git a/sprout/container/index_of.hpp b/sprout/container/index_of.hpp index feeacd6f..5a3f000c 100644 --- a/sprout/container/index_of.hpp +++ b/sprout/container/index_of.hpp @@ -23,8 +23,15 @@ namespace sprout { // ADL callable range_index_of(cont, p) -> range_index_of(cont, p) // [default] // Container is T[N] -> p - iterator(cont) + // otherwise, Container is not const + // && sprout::is_const_iterator_cast_convertible + // && (callable sprout::as_const(cont).index_of(p) + // || callable sprout::as_const(cont).begin() + // || ADL(without sprout) callable begin(sprout::as_const(cont)) + // ) + // -> sprout::index_of(sprout::as_const(cont), sprout::const_iterator_cast(p)) // otherwise, callable cont.index_of(p) -> cont.index_of(p) - // otherwise -> sprout::distance(begin(cont), p) + // otherwise -> sprout::distance(sprout::begin(cont), p) // template inline SPROUT_CONSTEXPR typename sprout::container_traits::size_type diff --git a/sprout/container/nth.hpp b/sprout/container/nth.hpp index 2d1028cf..ed6d5c88 100644 --- a/sprout/container/nth.hpp +++ b/sprout/container/nth.hpp @@ -23,6 +23,13 @@ namespace sprout { // ADL callable range_nth(cont, i) -> range_nth(cont, i) // [default] // Container is T[N] -> iterator(cont) + i + // otherwise, Container is not const + // && sprout::is_const_iterator_cast_convertible + // && (callable sprout::as_const(cont).nth(i) + // || callable sprout::as_const(cont).begin() + // || ADL(without sprout) callable begin(sprout::as_const(cont)) + // ) + // -> sprout::const_iterator_cast(sprout::nth(sprout::as_const(cont), i)) // otherwise, callable cont.nth(i) -> cont.nth(i) // otherwise -> sprout::next(sprout::begin(cont), i) // diff --git a/sprout/iterator/const_iterator_cast.hpp b/sprout/iterator/const_iterator_cast.hpp index 3c347116..966738d2 100644 --- a/sprout/iterator/const_iterator_cast.hpp +++ b/sprout/iterator/const_iterator_cast.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -21,7 +22,7 @@ namespace sprout { // template struct is_const_iterator_cast_convertible - : public sprout::false_type + : public sprout::is_same::type, typename std::remove_cv::type> {}; template struct is_const_iterator_cast_convertible @@ -105,6 +106,11 @@ namespace sprout { const_iterator_conversion(U* it) { return const_cast(it); } + template + inline SPROUT_CONSTEXPR T + const_iterator_conversion(T const& it) { + return it; + } } // namespace iterator_detail } // namespace sprout diff --git a/sprout/type_traits/is_const_cast_convertible.hpp b/sprout/type_traits/is_const_cast_convertible.hpp new file mode 100644 index 00000000..f20670ee --- /dev/null +++ b/sprout/type_traits/is_const_cast_convertible.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + 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_TYPE_TRAITS_IS_CONST_CAST_CONVERTIBLE_HPP +#define SPROUT_TYPE_TRAITS_IS_CONST_CAST_CONVERTIBLE_HPP + +#include +#include +#include +#include + +namespace sprout { + // + // is_const_cast_convertible + // + namespace detail { + template + struct is_const_cast_convertible_test { + public: + template< + typename FromU = From, + typename = typename sprout::identity(std::declval()))>::type + > + static sprout::true_type test(int); + static sprout::false_type test(...); + }; + } // namespace detail + template + struct is_const_cast_convertible + : public sprout::identity::test(0))>::type + {}; + +#if SPROUT_USE_VARIABLE_TEMPLATES + template + SPROUT_STATIC_CONSTEXPR bool is_const_cast_convertible_v = sprout::is_const_cast_convertible::value; +#endif // #if SPROUT_USE_VARIABLE_TEMPLATES +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_TRAITS_IS_CONST_CAST_CONVERTIBLE_HPP diff --git a/sprout/type_traits/relationship.hpp b/sprout/type_traits/relationship.hpp index 8864ae44..112b3aa2 100644 --- a/sprout/type_traits/relationship.hpp +++ b/sprout/type_traits/relationship.hpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include diff --git a/testspr/tools.hpp b/testspr/tools.hpp index 270080e7..22c7070d 100644 --- a/testspr/tools.hpp +++ b/testspr/tools.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/testspr/utility.hpp b/testspr/utility.hpp new file mode 100644 index 00000000..1364b857 --- /dev/null +++ b/testspr/utility.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + 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 TESTSPR_UTILITY_HPP +#define TESTSPR_UTILITY_HPP + +#include +#include +#include +#include + +namespace testspr { + // + // as_const + // + template + inline SPROUT_CONSTEXPR typename std::conditional< + std::is_lvalue_reference::value, + typename std::remove_reference::type const&, + typename std::remove_reference::type const&& + >::type + as_const(T&& t) { + return SPROUT_FORWARD(T, t); + } + + // + // as_non_const + // + template + inline SPROUT_CONSTEXPR typename std::conditional< + std::is_lvalue_reference::value, + typename std::remove_const::type>::type&, + typename std::remove_const::type>::type&& + >::type + as_non_const(T&& t) { + typedef typename std::conditional< + std::is_lvalue_reference::value, + typename std::remove_const::type>::type&, + typename std::remove_const::type>::type&& + >::type type; + return const_cast(t); + } +} // namespace testspr + +#endif // #ifndef TESTSPR_UTILITY_HPP