/*============================================================================= Copyright (c) 2011-2013 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_CONTAINER_TRAITS_HPP #define SPROUT_CONTAINER_CONTAINER_TRAITS_HPP #include #include #include #include #include #include #include #include #include #if SPROUT_USE_PTR_INDEX_ITERATOR_IMPLEMENTATION # include #endif namespace sprout { template struct container_traits; namespace detail { // // has_value_type // has_iterator // has_const_iterator // has_reference // has_const_reference // has_size_type // has_difference_type // has_pointer // has_const_pointer // has_static_size // SPROUT_HAS_XXX_TYPE_DEF_LAZY(value_type); SPROUT_HAS_XXX_TYPE_DEF_LAZY(iterator); SPROUT_HAS_XXX_TYPE_DEF_LAZY(const_iterator); SPROUT_HAS_XXX_TYPE_DEF_LAZY(reference); SPROUT_HAS_XXX_TYPE_DEF_LAZY(const_reference); SPROUT_HAS_XXX_TYPE_DEF_LAZY(size_type); SPROUT_HAS_XXX_TYPE_DEF_LAZY(difference_type); SPROUT_HAS_XXX_TYPE_DEF_LAZY(pointer); SPROUT_HAS_XXX_TYPE_DEF_LAZY(const_pointer); SPROUT_HAS_XXX_VALUE_DEF_LAZY(static_size); // // inherit_if_value_type // inherit_if_iterator // inherit_if_const_iterator // inherit_if_reference // inherit_if_const_reference // inherit_if_size_type // inherit_if_difference_type // inherit_if_pointer // inherit_if_const_pointer // inherit_if_static_size // SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(value_type); SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(iterator); SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(const_iterator); SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(reference); SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(const_reference); SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(size_type); SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(difference_type); SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(pointer); SPROUT_INHERIT_IF_XXX_TYPE_DEF_LAZY(const_pointer); SPROUT_INHERIT_IF_XXX_CONSTANT_DEF_LAZY(static_size); // // inherit_iterator_if_const_iterator // inherit_const_iterator_if_iterator // inherit_reference_if_const_reference // inherit_const_reference_if_reference // inherit_pointer_if_const_pointer // inherit_const_pointer_if_pointer // SPROUT_INHERIT_ALIAS_IF_XXX_TYPE_DEF_LAZY(iterator, const_iterator); SPROUT_INHERIT_ALIAS_IF_XXX_TYPE_DEF_LAZY(const_iterator, iterator); SPROUT_INHERIT_ALIAS_IF_XXX_TYPE_DEF_LAZY(reference, const_reference); SPROUT_INHERIT_ALIAS_IF_XXX_TYPE_DEF_LAZY(const_reference, reference); SPROUT_INHERIT_ALIAS_IF_XXX_TYPE_DEF_LAZY(pointer, const_pointer); SPROUT_INHERIT_ALIAS_IF_XXX_TYPE_DEF_LAZY(const_pointer, pointer); // // has_container_nosy_iterator // template struct has_container_nosy_iterator : public sprout::integral_constant< bool, sprout::detail::has_iterator::value || sprout::detail::has_const_iterator::value > {}; // // has_container_nosy_value_type // template struct has_container_nosy_value_type : public sprout::integral_constant< bool, sprout::detail::has_value_type::value || sprout::detail::has_container_nosy_iterator::value > {}; // // has_container_nosy_static_size // template struct has_container_nosy_static_size : public sprout::integral_constant< bool, sprout::detail::has_static_size::value || sprout::detail::is_array_like::value > {}; // // container_nosy_iterator // template struct container_nosy_iterator_impl {}; template struct container_nosy_iterator_impl : public sprout::detail::inherit_if_iterator {}; template struct container_nosy_iterator_impl : public sprout::detail::inherit_iterator_if_const_iterator {}; template struct container_nosy_iterator : public sprout::detail::container_nosy_iterator_impl< Container, sprout::detail::has_iterator::value, sprout::detail::has_const_iterator::value > {}; // // container_nosy_const_iterator // template struct container_nosy_const_iterator_impl {}; template struct container_nosy_const_iterator_impl : public sprout::detail::inherit_if_const_iterator {}; template struct container_nosy_const_iterator_impl : public sprout::detail::inherit_const_iterator_if_iterator {}; template struct container_nosy_const_iterator : public sprout::detail::container_nosy_const_iterator_impl< Container, sprout::detail::has_const_iterator::value, sprout::detail::has_iterator::value > {}; // // container_nosy_value_type // template struct container_nosy_value_type_impl {}; template struct container_nosy_value_type_impl { public: typedef typename Container::value_type value_type; }; template struct container_nosy_value_type_impl { public: typedef typename std::iterator_traits< typename sprout::detail::container_nosy_iterator::iterator >::value_type value_type; }; template struct container_nosy_value_type : public sprout::detail::container_nosy_value_type_impl< Container, sprout::detail::has_value_type::value, sprout::detail::has_container_nosy_iterator::value > {}; // // container_nosy_reference // template struct container_nosy_reference_impl {}; template struct container_nosy_reference_impl { public: typedef typename Container::reference reference; }; template struct container_nosy_reference_impl { public: typedef typename Container::const_reference reference; }; template struct container_nosy_reference_impl { public: typedef typename std::iterator_traits< typename sprout::detail::container_nosy_iterator::iterator >::reference reference; }; template struct container_nosy_reference : public sprout::detail::container_nosy_reference_impl< Container, sprout::detail::has_reference::value, sprout::detail::has_const_reference::value, sprout::detail::has_container_nosy_iterator::value > {}; // // container_nosy_const_reference // template struct container_nosy_const_reference_impl {}; template struct container_nosy_const_reference_impl { public: typedef typename Container::const_reference const_reference; }; template struct container_nosy_const_reference_impl { public: typedef typename Container::reference const_reference; }; template struct container_nosy_const_reference_impl { public: typedef typename std::iterator_traits< typename sprout::detail::container_nosy_const_iterator::const_iterator >::reference const_reference; }; template struct container_nosy_const_reference : public sprout::detail::container_nosy_const_reference_impl< Container, sprout::detail::has_const_reference::value, sprout::detail::has_reference::value, sprout::detail::has_container_nosy_iterator::value > {}; // // container_nosy_difference_type // template struct container_nosy_difference_type_impl { public: typedef std::ptrdiff_t difference_type; }; template struct container_nosy_difference_type_impl { public: typedef typename Container::difference_type difference_type; }; template struct container_nosy_difference_type_impl { public: typedef typename std::iterator_traits< typename sprout::detail::container_nosy_iterator::iterator >::difference_type difference_type; }; template struct container_nosy_difference_type : public sprout::detail::container_nosy_difference_type_impl< Container, sprout::detail::has_difference_type::value, sprout::detail::has_container_nosy_iterator::value > {}; // // container_nosy_size_type // template struct container_nosy_size_type_impl { public: typedef std::size_t size_type; }; template struct container_nosy_size_type_impl { public: typedef typename Container::size_type size_type; }; template struct container_nosy_size_type_impl { public: typedef typename std::make_unsigned< typename std::iterator_traits< typename sprout::detail::container_nosy_iterator::iterator >::difference_type >::type size_type; }; template struct container_nosy_size_type : public sprout::detail::container_nosy_size_type_impl< Container, sprout::detail::has_size_type::value, sprout::detail::has_container_nosy_iterator::value > {}; // // container_nosy_pointer // template struct container_nosy_pointer_impl {}; template struct container_nosy_pointer_impl { public: typedef typename Container::pointer pointer; }; template struct container_nosy_pointer_impl { public: typedef typename Container::const_pointer pointer; }; template struct container_nosy_pointer_impl { public: typedef typename sprout::detail::container_nosy_value_type::value_type* pointer; }; template struct container_nosy_pointer : public sprout::detail::container_nosy_pointer_impl< Container, sprout::detail::has_pointer::value, sprout::detail::has_const_pointer::value, sprout::detail::has_container_nosy_value_type::value > {}; // // container_nosy_const_pointer // template struct container_nosy_const_pointer_impl {}; template struct container_nosy_const_pointer_impl { public: typedef typename Container::const_pointer const_pointer; }; template struct container_nosy_const_pointer_impl { public: typedef typename Container::pointer const_pointer; }; template struct container_nosy_const_pointer_impl { public: typedef typename sprout::detail::container_nosy_value_type::value_type const* const_pointer; }; template struct container_nosy_const_pointer : public sprout::detail::container_nosy_const_pointer_impl< Container, sprout::detail::has_const_pointer::value, sprout::detail::has_pointer::value, sprout::detail::has_container_nosy_value_type::value > {}; // // container_nosy_static_size // template struct container_nosy_static_size_impl {}; template struct container_nosy_static_size_impl : public sprout::detail::inherit_if_static_size {}; template struct container_nosy_static_size_impl : public sprout::detail::inherit_if_static_size { public: SPROUT_STATIC_CONSTEXPR typename sprout::detail::array_like_static_size::value_type static_size = sprout::detail::array_like_static_size::value ; }; template SPROUT_CONSTEXPR_OR_CONST typename sprout::detail::array_like_static_size::value_type sprout::detail::container_nosy_static_size_impl::static_size ; template struct container_nosy_static_size : public sprout::detail::container_nosy_static_size_impl< Container, sprout::detail::has_static_size::value, sprout::detail::is_array_like::value > {}; // // container_nosy_fixed_size // template struct container_nosy_fixed_size_impl {}; template struct container_nosy_fixed_size_impl { public: static SPROUT_CONSTEXPR decltype(sprout::detail::container_nosy_static_size::static_size) fixed_size() SPROUT_NOEXCEPT { return sprout::detail::container_nosy_static_size::static_size; } }; template struct container_nosy_fixed_size : public sprout::detail::container_nosy_fixed_size_impl< Container, sprout::detail::has_container_nosy_static_size::value > {}; // // container_traits_default // template struct container_traits_default : public sprout::detail::container_nosy_value_type , public sprout::detail::container_nosy_iterator , public sprout::detail::container_nosy_const_iterator , public sprout::detail::container_nosy_reference , public sprout::detail::container_nosy_const_reference , public sprout::detail::container_nosy_size_type , public sprout::detail::container_nosy_difference_type , public sprout::detail::container_nosy_pointer , public sprout::detail::container_nosy_const_pointer , public sprout::detail::container_nosy_static_size , public sprout::detail::container_nosy_fixed_size {}; template 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; typedef std::ptrdiff_t difference_type; typedef T* pointer; typedef T const* const_pointer; public: SPROUT_STATIC_CONSTEXPR size_type static_size = N; public: static SPROUT_CONSTEXPR size_type fixed_size() SPROUT_NOEXCEPT { return static_size; } }; template SPROUT_CONSTEXPR_OR_CONST typename sprout::detail::container_traits_default::size_type sprout::detail::container_traits_default::static_size; // // container_traits_const_default // template struct container_traits_const_default : public sprout::detail::inherit_if_value_type > , public sprout::detail::inherit_if_const_iterator > , public sprout::detail::inherit_if_const_reference > , public sprout::detail::inherit_if_size_type > , public sprout::detail::inherit_if_difference_type > , public sprout::detail::inherit_if_const_pointer > , public sprout::detail::inherit_if_static_size > , public sprout::detail::container_nosy_fixed_size > , public sprout::detail::inherit_iterator_if_const_iterator > , public sprout::detail::inherit_reference_if_const_reference > , public sprout::detail::inherit_pointer_if_const_pointer > {}; } // namespace detail // // container_traits // template struct container_traits : public sprout::detail::container_traits_default {}; template struct container_traits : public sprout::detail::container_traits_const_default {}; template struct container_traits : public sprout::detail::container_traits_default {}; template struct container_traits : public sprout::detail::container_traits_const_default {}; // // container_traits_facade // template struct container_traits_facade : public sprout::detail::inherit_if_value_type > , public sprout::detail::inherit_if_iterator > , public sprout::detail::inherit_if_const_iterator > , public sprout::detail::inherit_if_reference > , public sprout::detail::inherit_if_const_reference > , public sprout::detail::inherit_if_size_type > , public sprout::detail::inherit_if_difference_type > , public sprout::detail::inherit_if_pointer > , public sprout::detail::inherit_if_const_pointer > , public sprout::detail::inherit_if_static_size > , public sprout::detail::container_nosy_fixed_size > {}; // // is_fixed_container // template struct is_fixed_container : public sprout::detail::has_static_size > {}; namespace detail { // // static_size_or_zero // template struct static_size_or_zero; template struct static_size_or_zero< Container, typename std::enable_if >::value>::type > : public sprout::integral_constant< typename sprout::container_traits::size_type, sprout::container_traits::static_size > {}; template struct static_size_or_zero< Container, typename std::enable_if >::value>::type > : public sprout::integral_constant< typename sprout::container_traits::size_type, 0 > {}; } // namespace sprout } // namespace sprout #endif // #ifndef SPROUT_CONTAINER_CONTAINER_TRAITS_HPP