diff --git a/sprout/config/suffix.hpp b/sprout/config/suffix.hpp index 1cac8d53..054bf319 100644 --- a/sprout/config/suffix.hpp +++ b/sprout/config/suffix.hpp @@ -100,4 +100,10 @@ # define SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION 0 #endif // #ifndef SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION +#ifndef SPROUT_CONFIG_DISABLE_SUPPORT_EFFICIENT_ARRAY_ITERATION +# define SPROUT_USE_PTR_INDEX_ITERATOR_IMPLEMENTATION 1 +#else // #ifndef SPROUT_CONFIG_DISABLE_SUPPORT_EFFICIENT_ARRAY_ITERATION +# define SPROUT_USE_PTR_INDEX_ITERATOR_IMPLEMENTATION 0 +#endif // #ifndef SPROUT_CONFIG_DISABLE_SUPPORT_EFFICIENT_ARRAY_ITERATION + #endif // #ifndef SPROUT_CONFIG_SUFFIX_HPP diff --git a/sprout/container/begin.hpp b/sprout/container/begin.hpp index c5397e7d..ded390bc 100644 --- a/sprout/container/begin.hpp +++ b/sprout/container/begin.hpp @@ -22,6 +22,19 @@ namespace sprout { range_begin(Container const& cont) { return cont.begin(); } + + template + inline typename sprout::container_traits::iterator + range_begin(T (& arr)[N]) { + typedef typename sprout::container_traits::iterator iterator; + return iterator(arr); + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::const_iterator + range_begin(T const (& arr)[N]) { + typedef typename sprout::container_traits::const_iterator iterator; + return iterator(arr); + } } // namespace container_detail } // namespace sprout @@ -46,12 +59,12 @@ namespace sprout { template inline typename sprout::container_traits::iterator begin(T (& arr)[N]) { - return arr; + return sprout::container_detail::range_begin(arr); } template inline SPROUT_CONSTEXPR typename sprout::container_traits::const_iterator begin(T const (& arr)[N]) { - return arr; + return sprout::container_detail::range_begin(arr); } // @@ -67,7 +80,7 @@ namespace sprout { template inline SPROUT_CONSTEXPR typename sprout::container_traits::const_iterator cbegin(T const (& arr)[N]) { - return arr; + return sprout::container_detail::range_begin(arr); } } // namespace sprout diff --git a/sprout/container/container_traits.hpp b/sprout/container/container_traits.hpp index 2bcde15a..3afb36f1 100644 --- a/sprout/container/container_traits.hpp +++ b/sprout/container/container_traits.hpp @@ -9,6 +9,9 @@ #include #include #include +#if SPROUT_USE_PTR_INDEX_ITERATOR_IMPLEMENTATION +# include +#endif namespace sprout { template @@ -428,8 +431,13 @@ namespace sprout { struct container_traits_default { public: typedef T value_type; +#if SPROUT_USE_PTR_INDEX_ITERATOR_IMPLEMENTATION + typedef sprout::ptr_index_iterator iterator; + typedef sprout::ptr_index_iterator const_iterator; +#else typedef T* iterator; typedef T const* const_iterator; +#endif typedef T& reference; typedef T const& const_reference; typedef std::size_t size_type; diff --git a/sprout/container/end.hpp b/sprout/container/end.hpp index dc150daa..4ab01e4e 100644 --- a/sprout/container/end.hpp +++ b/sprout/container/end.hpp @@ -22,6 +22,19 @@ namespace sprout { range_end(Container const& cont) { return cont.end(); } + + template + inline typename sprout::container_traits::iterator + range_end(T (& arr)[N]) { + typedef typename sprout::container_traits::iterator iterator; + return iterator(arr) + N; + } + template + inline SPROUT_CONSTEXPR typename sprout::container_traits::const_iterator + range_end(T const (& arr)[N]) { + typedef typename sprout::container_traits::const_iterator iterator; + return iterator(arr) + N; + } } // namespace container_detail } // namespace sprout @@ -46,12 +59,12 @@ namespace sprout { template inline typename sprout::container_traits::iterator end(T (& arr)[N]) { - return arr + N; + return sprout::container_detail::range_end(arr); } template inline SPROUT_CONSTEXPR typename sprout::container_traits::const_iterator end(T const (& arr)[N]) { - return arr + N; + return sprout::container_detail::range_end(arr); } // @@ -67,7 +80,7 @@ namespace sprout { template inline SPROUT_CONSTEXPR typename sprout::container_traits::const_iterator cend(T const (& arr)[N]) { - return arr + N; + return sprout::container_detail::range_end(arr); } } // namespace sprout diff --git a/sprout/cstring/strlen.hpp b/sprout/cstring/strlen.hpp index 61d8d5c3..44809ff9 100644 --- a/sprout/cstring/strlen.hpp +++ b/sprout/cstring/strlen.hpp @@ -5,21 +5,12 @@ #include namespace sprout { - // Copyright (C) 2011 RiSK (sscrisk) - - namespace detail { - inline SPROUT_CONSTEXPR std::size_t - strlen_impl(char const* s, std::size_t n) { - return !*s ? n : - sprout::detail::strlen_impl(s + 1, n + 1) - ; - } - } // namespace detail - // 7.21.6.3 strlen ֐ inline SPROUT_CONSTEXPR std::size_t strlen(char const* s) { - return sprout::detail::strlen_impl(s, 0); + return !*s ? 0 + : 1 + sprout::strlen(s + 1) + ; } } // namespace sprout diff --git a/sprout/cwchar/wcslen.hpp b/sprout/cwchar/wcslen.hpp index 1a68ba4a..b901a4c7 100644 --- a/sprout/cwchar/wcslen.hpp +++ b/sprout/cwchar/wcslen.hpp @@ -5,20 +5,11 @@ #include namespace sprout { - // Copyright (C) 2011 RiSK (sscrisk) - - namespace detail { - inline SPROUT_CONSTEXPR std::size_t - wcslen_impl(wchar_t const* s, std::size_t n) { - return !*s ? n : - sprout::detail::wcslen_impl(s + 1, n + 1) - ; - } - } // namespace detail - inline SPROUT_CONSTEXPR std::size_t wcslen(wchar_t const* s) { - return sprout::detail::wcslen_impl(s, 0); + return !*s ? 0 + : 1 + sprout::wcslen(s + 1) + ; } } // namespace sprout diff --git a/sprout/iterator/index_iterator.hpp b/sprout/iterator/index_iterator.hpp index 2de357cb..b8ccc67d 100644 --- a/sprout/iterator/index_iterator.hpp +++ b/sprout/iterator/index_iterator.hpp @@ -20,27 +20,27 @@ namespace sprout { class index_iterator : public std::iterator< std::random_access_iterator_tag, - typename sprout::container_traits::type>::value_type, - typename sprout::container_traits::type>::difference_type, + typename sprout::container_traits::type>::value_type, + typename sprout::container_traits::type>::difference_type, typename std::conditional< std::is_const::type>::value, - typename sprout::container_traits::type>::const_pointer, - typename sprout::container_traits::type>::pointer + typename sprout::container_traits::type>::const_pointer, + typename sprout::container_traits::type>::pointer >::type, typename std::conditional< std::is_const::type>::value, - typename sprout::container_traits::type>::const_reference, - typename sprout::container_traits::type>::reference + typename sprout::container_traits::type>::const_reference, + typename sprout::container_traits::type>::reference >::type > { public: typedef Container container_type; - typedef typename sprout::container_traits::type> traits_type; + typedef typename sprout::container_traits::type> traits_type; typedef typename std::conditional< std::is_reference::value, - typename std::decay::type const&, - typename std::decay::type const + typename std::remove_reference::type const&, + typename std::remove_reference::type const >::type const_container_type; private: typedef std::iterator< @@ -58,6 +58,7 @@ namespace sprout { typename traits_type::reference >::type > base_type; + typedef sprout::value_holder holder_type; public: typedef typename base_type::iterator_category iterator_category; typedef typename base_type::value_type value_type; @@ -66,10 +67,10 @@ namespace sprout { typedef typename base_type::reference reference; typedef typename traits_type::size_type size_type; private: - sprout::value_holder holder_; + holder_type holder_; size_type index_; private: - SPROUT_CONSTEXPR index_iterator(sprout::value_holder const& r, size_type index) + SPROUT_CONSTEXPR index_iterator(holder_type const& r, size_type index) : holder_(r) , index_(index) {} @@ -79,13 +80,23 @@ namespace sprout { , index_() {} index_iterator(index_iterator const&) = default; - SPROUT_CONSTEXPR index_iterator(typename sprout::value_holder::param_type p, size_type index) + explicit SPROUT_CONSTEXPR index_iterator(typename holder_type::param_type p) + : holder_(p) + , index_(0) + {} + SPROUT_CONSTEXPR index_iterator(typename holder_type::param_type p, size_type index) : holder_(p) , index_(index) {} operator index_iterator() const { return index_iterator(holder_.get(), index_); } + SPROUT_CONSTEXPR typename holder_type::mutable_or_const_reference base() const { + return holder_.get(); + } + SPROUT_CONSTEXPR size_type index() const { + return index_; + } SPROUT_CONSTEXPR index_iterator next() const { return index_iterator(holder_, index_ + 1); } diff --git a/sprout/iterator/ptr_index_iterator.hpp b/sprout/iterator/ptr_index_iterator.hpp new file mode 100644 index 00000000..83c76ce2 --- /dev/null +++ b/sprout/iterator/ptr_index_iterator.hpp @@ -0,0 +1,286 @@ +#ifndef SPROUT_ITERATOR_PTR_INDEX_ITERATOR_HPP +#define SPROUT_ITERATOR_PTR_INDEX_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + // + // ptr_index_iterator + // + template + class ptr_index_iterator + : public std::iterator< + typename std::iterator_traits::iterator_category, + typename std::iterator_traits::value_type, + typename std::iterator_traits::difference_type, + typename std::iterator_traits::pointer, + typename std::iterator_traits::reference + > + { + public: + typedef T type; + private: + typedef std::iterator< + typename std::iterator_traits::iterator_category, + typename std::iterator_traits::value_type, + typename std::iterator_traits::difference_type, + typename std::iterator_traits::pointer, + typename std::iterator_traits::reference + > base_type; + public: + typedef typename base_type::iterator_category iterator_category; + typedef typename base_type::value_type value_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::reference reference; + typedef typename std::remove_pointer::type const* const_pointer; + private: + pointer p_; + difference_type index_; + public: + SPROUT_CONSTEXPR ptr_index_iterator() + : p_() + , index_() + {} + ptr_index_iterator(ptr_index_iterator const&) = default; + explicit SPROUT_CONSTEXPR ptr_index_iterator(pointer p) + : p_(p) + , index_(0) + {} + SPROUT_CONSTEXPR ptr_index_iterator(pointer p, difference_type index) + : p_(p) + , index_(index) + {} + operator ptr_index_iterator() const { + return ptr_index_iterator(p_, index_); + } + SPROUT_CONSTEXPR pointer base() const { + return p_; + } + SPROUT_CONSTEXPR difference_type index() const { + return index_; + } + SPROUT_CONSTEXPR pointer ptr() const { + return p_ + index_; + } + SPROUT_CONSTEXPR ptr_index_iterator next() const { + return ptr_index_iterator(p_, index_ + 1); + } + SPROUT_CONSTEXPR ptr_index_iterator prev() const { + return ptr_index_iterator(p_, index_ - 1); + } + void swap(ptr_index_iterator& other) + SPROUT_NOEXCEPT + { + sprout::swap(p_, other.p_); + sprout::swap(index_, other.index_); + } + friend SPROUT_CONSTEXPR bool operator==(ptr_index_iterator const& lhs, ptr_index_iterator const& rhs) { + return lhs.index_ == rhs.index_; + } + friend SPROUT_CONSTEXPR bool operator!=(ptr_index_iterator const& lhs, ptr_index_iterator const& rhs) { + return !(lhs == rhs); + } + friend SPROUT_CONSTEXPR bool operator<(ptr_index_iterator const& lhs, ptr_index_iterator const& rhs) { + return lhs.index_ < rhs.index_; + } + friend SPROUT_CONSTEXPR bool operator>(ptr_index_iterator const& lhs, ptr_index_iterator const& rhs) { + return rhs < lhs; + } + friend SPROUT_CONSTEXPR bool operator<=(ptr_index_iterator const& lhs, ptr_index_iterator const& rhs) { + return !(rhs < lhs); + } + friend SPROUT_CONSTEXPR bool operator>=(ptr_index_iterator const& lhs, ptr_index_iterator const& rhs) { + return !(lhs < rhs); + } + SPROUT_CONSTEXPR reference operator*() const { + return p_[index_]; + } + SPROUT_CONSTEXPR pointer operator->() const { + return p_ + index_; + } + ptr_index_iterator& operator++() { + ptr_index_iterator temp(next()); + temp.swap(*this); + return *this; + } + ptr_index_iterator operator++(int) { + ptr_index_iterator result(*this); + ++*this; + return result; + } + ptr_index_iterator& operator--() { + ptr_index_iterator temp(prev()); + temp.swap(*this); + return *this; + } + ptr_index_iterator operator--(int) { + ptr_index_iterator result(*this); + --*this; + return result; + } + SPROUT_CONSTEXPR ptr_index_iterator operator+(difference_type n) const { + return ptr_index_iterator(p_, index_ + n); + } + SPROUT_CONSTEXPR ptr_index_iterator operator-(difference_type n) const { + return ptr_index_iterator(p_, index_ - n); + } + ptr_index_iterator& operator+=(difference_type n) { + ptr_index_iterator temp(p_, index_ + n); + temp.swap(*this); + return *this; + } + ptr_index_iterator& operator-=(difference_type n) { + ptr_index_iterator temp(p_, index_ - n); + temp.swap(*this); + return *this; + } + SPROUT_CONSTEXPR reference operator[](difference_type n) const { + return p_[index_ + n]; + } + friend SPROUT_CONSTEXPR difference_type operator-(ptr_index_iterator const& lhs, ptr_index_iterator const& rhs) { + return lhs.index_ - rhs.index_; + } + friend SPROUT_CONSTEXPR ptr_index_iterator operator+(difference_type n, ptr_index_iterator const& it) { + return it + n; + } + }; + + // + // swap + // + template + inline void + swap(sprout::ptr_index_iterator& lhs, sprout::ptr_index_iterator& rhs) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { + lhs.swap(rhs); + } + + // + // make_ptr_index_iterator + // + template + inline SPROUT_CONSTEXPR sprout::ptr_index_iterator + make_ptr_index_iterator(T* p) { + return sprout::ptr_index_iterator(p); + } + template + inline SPROUT_CONSTEXPR sprout::ptr_index_iterator + make_ptr_index_iterator(T* p, typename sprout::ptr_index_iterator::difference_type index) { + return sprout::ptr_index_iterator(p, index); + } + + // + // as_iterator + // + template + inline SPROUT_CONSTEXPR sprout::ptr_index_iterator + as_iterator(T* p) { + return sprout::make_ptr_index_iterator(p); + } + template + inline SPROUT_CONSTEXPR sprout::ptr_index_iterator + as_iterator(T* p, typename std::iterator_traits::difference_type n) { + return sprout::make_ptr_index_iterator(p, n); + } + + template + inline SPROUT_CONSTEXPR Iterator + as_iterator(Iterator const& it) { + return it; + } + template + inline SPROUT_CONSTEXPR Iterator + as_iterator(Iterator const& it, typename std::iterator_traits::difference_type n) { + return sprout::next(it, n); + } + + // + // as_iterator_base + // + template + inline SPROUT_CONSTEXPR typename sprout::ptr_index_iterator::pointer + as_iterator_base(sprout::ptr_index_iterator const& it) { + return it.ptr(); + } + template + inline SPROUT_CONSTEXPR Iterator + as_iterator_base(Iterator const& it) { + return it; + } + + // + // is_ptr_index_iterator + // + template + struct is_ptr_index_iterator + : public std::false_type + {}; + template + struct is_ptr_index_iterator + : public sprout::is_ptr_index_iterator + {}; + template + struct is_ptr_index_iterator + : public sprout::is_ptr_index_iterator + {}; + template + struct is_ptr_index_iterator > + : public std::true_type + {}; + + // + // iterator_distance + // + template + inline SPROUT_CONSTEXPR typename std::iterator_traits >::difference_type + iterator_distance(sprout::ptr_index_iterator first, sprout::ptr_index_iterator last) { + return last - first; + } + + // + // iterator_next + // + template + inline SPROUT_CONSTEXPR sprout::ptr_index_iterator + iterator_next(sprout::ptr_index_iterator const& it) { + return it.next(); + } + template + inline SPROUT_CONSTEXPR sprout::ptr_index_iterator + iterator_next( + sprout::ptr_index_iterator const& it, + typename sprout::ptr_index_iterator::difference_type n + ) + { + return it + n; + } + + // + // iterator_prev + // + template + inline SPROUT_CONSTEXPR sprout::ptr_index_iterator + iterator_prev(sprout::ptr_index_iterator const& it) { + return it.prev(); + } + template + inline SPROUT_CONSTEXPR sprout::ptr_index_iterator + iterator_prev( + sprout::ptr_index_iterator const& it, + typename sprout::ptr_index_iterator::difference_type n + ) + { + return it - n; + } +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_PTR_INDEX_ITERATOR_HPP diff --git a/sprout/iterator/various.hpp b/sprout/iterator/various.hpp index 32e9b38d..07f0109a 100644 --- a/sprout/iterator/various.hpp +++ b/sprout/iterator/various.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include diff --git a/sprout/string/char_traits.hpp b/sprout/string/char_traits.hpp index 5718db3e..b7c4b699 100644 --- a/sprout/string/char_traits.hpp +++ b/sprout/string/char_traits.hpp @@ -5,6 +5,10 @@ #include #include #include +#include +#include +#include HDR_ALGORITHM_SSCRISK_CEL_OR_SPROUT +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT namespace sprout { // @@ -20,6 +24,19 @@ namespace sprout { typedef typename impl_type::off_type off_type; typedef typename impl_type::pos_type pos_type; typedef typename impl_type::state_type state_type; + private: + struct eq_ { + public: + SPROUT_CONSTEXPR bool operator()(char_type c1, char_type c2) const SPROUT_NOEXCEPT { + return eq(c1, c2); + } + }; + private: + static SPROUT_CONSTEXPR char_type const* find_impl(char_type const* found, char_type const* last) { + return found == last ? nullptr + : found + ; + } public: static void assign(char_type& c1, char_type const& c2) SPROUT_NOEXCEPT { impl_type::assign(c1, c2); @@ -43,10 +60,15 @@ namespace sprout { ; } static SPROUT_CONSTEXPR char_type const* find(char_type const* s, std::size_t n, char_type const& a) { - return !n ? nullptr - : eq(*s, a) ? s - : find(s + 1, n - 1, a) - ; + return find_impl( + sprout::as_iterator_base( + NS_SSCRISK_CEL_OR_SPROUT::find_if( + sprout::as_iterator(s), sprout::as_iterator(s, n), + sprout::bind2nd(eq_(), a) + ) + ), + s + n + ); } static char_type* move(char_type* s1, char_type const* s2, std::size_t n) { return impl_type::move(s1, s2, n); @@ -105,10 +127,12 @@ namespace sprout { } template static SPROUT_CONSTEXPR ConstIterator find(ConstIterator s, std::size_t n, char_type const& a) { - return !n ? s - : eq(*s, a) ? s - : find(s + 1, n - 1, a) - ; + return sprout::as_iterator_base( + NS_SSCRISK_CEL_OR_SPROUT::find_if( + s, s + n, + sprout::bind2nd(eq_(), a) + ) + ); } template static Iterator move(Iterator s1, ConstIterator s2, std::size_t n) { @@ -140,23 +164,45 @@ namespace sprout { typedef typename traits_type::off_type off_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::state_type state_type; + private: + struct eq_ { + public: + SPROUT_CONSTEXPR bool operator()(char_type c1, char_type c2) const SPROUT_NOEXCEPT { + return traits_type::eq(c1, c2); + } + }; public: + static SPROUT_CONSTEXPR std::size_t length(char_type const* s, std::size_t n) { + return NS_SSCRISK_CEL_OR_SPROUT::distance( + sprout::as_iterator(s), + find(sprout::as_iterator(s), n, char_type()) + ); + } static SPROUT_CONSTEXPR char_type const* find(char_type const* s, std::size_t n, char_type const& a) { - return !n ? s - : traits_type::eq(*s, a) ? s - : find(s + 1, n - 1, a) - ; + return sprout::as_iterator_base( + NS_SSCRISK_CEL_OR_SPROUT::find_if( + sprout::as_iterator(s), sprout::as_iterator(s, n), + sprout::bind2nd(eq_(), a) + ) + ); } static SPROUT_CONSTEXPR bool is_found(char_type const* found, char_type const* last) { return found != last; } #if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION + template + static SPROUT_CONSTEXPR std::size_t length(ConstIterator s, std::size_t n) { + return NS_SSCRISK_CEL_OR_SPROUT::distance( + s, + find(s, n, char_type()) + ); + } template static SPROUT_CONSTEXPR ConstIterator find(ConstIterator s, std::size_t n, char_type const& a) { - return !n ? s - : traits_type::eq(*s, a) ? s - : find(s + 1, n - 1, a) - ; + return NS_SSCRISK_CEL_OR_SPROUT::find_if( + s, s + n, + sprout::bind2nd(eq_(), a) + ); } template static SPROUT_CONSTEXPR bool is_found(ConstIterator found, ConstIterator last) { diff --git a/sprout/string/concat.hpp b/sprout/string/concat.hpp index 51082ef9..25f7c075 100644 --- a/sprout/string/concat.hpp +++ b/sprout/string/concat.hpp @@ -126,17 +126,19 @@ namespace sprout { template inline SPROUT_CONSTEXPR sprout::basic_string operator+(sprout::basic_string const& lhs, T const (& rhs)[M]) { + typedef sprout::char_traits_helper traits_type; return sprout::detail::string_concat( lhs, lhs.size(), - rhs, sprout::char_traits::length(rhs), + rhs, traits_type::length(rhs, M - 1), sprout::index_range<0, N + (M - 1)>::make() ); } template inline SPROUT_CONSTEXPR sprout::basic_string operator+(T const (& lhs)[M], sprout::basic_string const& rhs) { + typedef sprout::char_traits_helper traits_type; return sprout::detail::string_concat( - lhs, sprout::char_traits::length(lhs), + lhs, traits_type::length(lhs, M - 1), rhs, rhs.size(), sprout::index_range<0, (M - 1) + N>::make() ); diff --git a/sprout/string/string.hpp b/sprout/string/string.hpp index d4448226..cedad5b0 100644 --- a/sprout/string/string.hpp +++ b/sprout/string/string.hpp @@ -874,7 +874,8 @@ namespace sprout { template inline SPROUT_CONSTEXPR sprout::basic_string to_string_impl(T const(& arr)[N], sprout::index_tuple) { - return to_string_impl_1(arr, sprout::char_traits::length(arr), sprout::index_tuple()); + typedef sprout::char_traits_helper > traits_type; + return to_string_impl_1(arr, traits_type::length(arr, N - 1), sprout::index_tuple()); } } // namespace detail // diff --git a/sprout/variant.hpp b/sprout/variant.hpp index 4fc2dc61..8da23dae 100644 --- a/sprout/variant.hpp +++ b/sprout/variant.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/sprout/variant/as_visitor.hpp b/sprout/variant/as_visitor.hpp new file mode 100644 index 00000000..85b298ad --- /dev/null +++ b/sprout/variant/as_visitor.hpp @@ -0,0 +1,82 @@ +#ifndef SPROUT_VARIANT_AS_VISITOR_HPP +#define SPROUT_VARIANT_AS_VISITOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + struct result_type_or_void; + template + struct result_type_or_void< + T, + typename std::enable_if >::value>::type + > { + public: + typedef typename sprout::weak_result_type::result_type type; + }; + template + struct result_type_or_void< + T, + typename std::enable_if >::value>::type + > { + public: + typedef void type; + }; + } // namespace detail + + // + // visitor_wrapper + // + template< + typename Visitor, + typename R = typename sprout::detail::result_type_or_void::type + > + class visitor_wrapper + : public sprout::static_visitor + { + public: + typedef Visitor visitor_type; + typedef sprout::value_holder holder_type; + private: + holder_type v_; + public: + SPROUT_CONSTEXPR explicit visitor_wrapper(typename holder_type::param_type v) + : v_(v) + {} + template + SPROUT_CONSTEXPR auto operator()(T&& t) + -> decltype(std::declval().get()(sprout::forward(t))) const + { + return v_.get()(sprout::forward(t)); + } + }; + + // + // as_visitor + // + template + inline SPROUT_CONSTEXPR sprout::visitor_wrapper::type>::type> + as_visitor(Visitor&& visitor) { + typedef sprout::visitor_wrapper::type>::type> type; + return type(sprout::lvalue_forward(visitor)); + } + + template + inline SPROUT_CONSTEXPR sprout::visitor_wrapper::type>::type, R> + as_visitor(Visitor&& visitor) { + typedef sprout::visitor_wrapper::type>::type, R> type; + return type(sprout::lvalue_forward(visitor)); + } +} // namespace sprout + +#endif // #ifndef SPROUT_VARIANT_AS_VISITOR_HPP