/*============================================================================= Copyright (c) 2011-2019 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_TUPLE_FLEX_HPP #define SPROUT_TUPLE_FLEX_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include namespace sprout { namespace tuples { // // flex_tuple // template class flex_tuple { public: typedef sprout::tuples::tuple tuple_type; private: typedef sprout::value_holder holder_type; private: holder_type holder_; public: flex_tuple(flex_tuple const&) = default; flex_tuple(flex_tuple&&) = default; SPROUT_CONSTEXPR flex_tuple(tuple_type const& t) : holder_(t) {} SPROUT_CONSTEXPR operator tuple_type const&() const { return holder_.get(); } template SPROUT_CONSTEXPR operator sprout::tuples::tuple() const { return sprout::tuples::tuple(sprout::tuples::flexibly_construct, holder_.get()); } }; // // flex // template inline SPROUT_CONSTEXPR T const& flex(T const& t) { return t; } template inline SPROUT_CONSTEXPR sprout::tuples::flex_tuple flex(sprout::tuples::tuple const& t) { return sprout::tuples::flex_tuple(t); } template inline SPROUT_CONSTEXPR To flex(sprout::tuples::tuple const& t) { return sprout::tuples::flex(t); } // // recursive_flex_tuple // template class recursive_flex_tuple : public sprout::tuples::flex_tuple { private: typedef sprout::tuples::flex_tuple base_type; private: template static SPROUT_CONSTEXPR sprout::tuples::tuple implicit_conversion_impl(typename base_type::tuple_type const& t, sprout::index_tuple) { return sprout::tuples::tuple( sprout::tuples::flexibly_construct, sprout::tuples::flex(sprout::tuples::get(t))... ); } public: recursive_flex_tuple(recursive_flex_tuple const&) = default; recursive_flex_tuple(recursive_flex_tuple&&) = default; SPROUT_CONSTEXPR recursive_flex_tuple(typename base_type::tuple_type const& t) : base_type(t) {} template SPROUT_CONSTEXPR operator sprout::tuples::tuple() const { return implicit_conversion_impl(*this, sprout::make_index_tuple::make()); } }; // // recursive_flex // template inline SPROUT_CONSTEXPR T const& recursive_flex(T const& t) { return t; } template inline SPROUT_CONSTEXPR sprout::tuples::recursive_flex_tuple recursive_flex(sprout::tuples::tuple const& t) { return sprout::tuples::recursive_flex_tuple(t); } template inline SPROUT_CONSTEXPR To recursive_flex(sprout::tuples::tuple const& t) { return sprout::tuples::recursive_flex(t); } // // common_flex_type // template struct common_flex_type; template struct common_flex_type : public sprout::common_decay {}; namespace detail { template struct common_flex_type_impl_2; template struct common_flex_type_impl_2 > : public sprout::identity< sprout::tuples::tuple< typename sprout::tuples::common_flex_type< typename sprout::tuples::tuple_element::type, typename sprout::tuples::tuple_element::type >::type... > > {}; template struct common_flex_type_impl_1; template struct common_flex_type_impl_1::value < sprout::tuples::tuple_size::value)>::type> : public sprout::tuples::common_flex_type {}; template struct common_flex_type_impl_1::value > sprout::tuples::tuple_size::value)>::type> : public sprout::tuples::common_flex_type {}; template struct common_flex_type_impl_1::value == sprout::tuples::tuple_size::value)>::type> : public sprout::tuples::detail::common_flex_type_impl_2::type> {}; template struct common_flex_type_impl; template struct common_flex_type_impl::value && sprout::tuples::is_tuple::value)>::type> : public sprout::tuples::detail::common_flex_type_impl_1 {}; template struct common_flex_type_impl::value && sprout::tuples::is_tuple::value)>::type> : public sprout::common_decay {}; } // namespace detail template struct common_flex_type : public sprout::tuples::detail::common_flex_type_impl {}; template struct common_flex_type : public sprout::tuples::common_flex_type::type, Tail...> {}; // // common_recursive_flex_type // template struct common_recursive_flex_type; template struct common_recursive_flex_type : public sprout::tuples::common_flex_type {}; namespace detail { template struct common_recursive_flex_type_impl_2; template struct common_recursive_flex_type_impl_2 > : public sprout::identity< sprout::tuples::tuple< typename sprout::tuples::common_recursive_flex_type< typename sprout::tuples::tuple_element::type, typename sprout::tuples::tuple_element::type >::type... > > {}; template struct common_recursive_flex_type_impl_1; template struct common_recursive_flex_type_impl_1::value < sprout::tuples::tuple_size::value)>::type> : public sprout::tuples::common_recursive_flex_type {}; template struct common_recursive_flex_type_impl_1::value > sprout::tuples::tuple_size::value)>::type> : public sprout::tuples::common_recursive_flex_type {}; template struct common_recursive_flex_type_impl_1::value == sprout::tuples::tuple_size::value)>::type> : public sprout::tuples::detail::common_recursive_flex_type_impl_2::type> {}; template struct common_recursive_flex_type_impl; template struct common_recursive_flex_type_impl::value && sprout::tuples::is_tuple::value)>::type> : public sprout::tuples::detail::common_recursive_flex_type_impl_1 {}; template struct common_recursive_flex_type_impl::value && sprout::tuples::is_tuple::value)>::type> : public sprout::tuples::common_flex_type {}; } // namespace detail template struct common_recursive_flex_type : public sprout::tuples::detail::common_recursive_flex_type_impl {}; template struct common_recursive_flex_type : public sprout::tuples::common_recursive_flex_type::type, Tail...> {}; } // namespace tuples using sprout::tuples::flex_tuple; using sprout::tuples::flex; using sprout::tuples::recursive_flex_tuple; using sprout::tuples::recursive_flex; using sprout::tuples::common_flex_type; using sprout::tuples::common_recursive_flex_type; } // namespace sprout #endif // #ifndef SPROUT_TUPLE_FLEX_HPP