From 3b0ab6f5fd1c40b1ad45e5c7dcc9c540c21e728d Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Sat, 20 Sep 2014 12:55:29 +0900 Subject: [PATCH] reimplementation tuple class --- README.rst | 2 +- sprout/tpp/algorithm/all_of.hpp | 52 ++-- sprout/tpp/algorithm/any_of.hpp | 53 ++-- sprout/tpp/algorithm/none_of.hpp | 53 ++-- sprout/tpp/algorithm/one_of.hpp | 102 +++++-- sprout/tuple/tuple/get.hpp | 19 +- sprout/tuple/tuple/tuple.hpp | 27 +- sprout/tuple/tuple/tuple_decl.hpp | 473 +++++++++++++++--------------- sprout/type/type_tuple.hpp | 6 + sprout/utility/eat.hpp | 21 ++ sprout/utility/operation.hpp | 1 + 11 files changed, 438 insertions(+), 371 deletions(-) create mode 100644 sprout/utility/eat.hpp diff --git a/README.rst b/README.rst index 3597a13a..0a1cc00b 100644 --- a/README.rst +++ b/README.rst @@ -36,7 +36,7 @@ Supported Compilers Linux: * GCC, C++11/14 mode: 4.7.0, 4.7.1, 4.7.2, 4.7.3, 4.7.4, 4.8.0, 4.8.1, 4.8.2, 4.8.3, 4.9.0 -* Clang, C++11/14 mode: 3.2, 3.3, 3.4, 3.4.1 +* Clang, C++11/14 mode: 3.2, 3.3, 3.4, 3.4.1, 3.5.0 ******************************************************************************* Author diff --git a/sprout/tpp/algorithm/all_of.hpp b/sprout/tpp/algorithm/all_of.hpp index 474f3f91..ea28f6ae 100644 --- a/sprout/tpp/algorithm/all_of.hpp +++ b/sprout/tpp/algorithm/all_of.hpp @@ -10,47 +10,43 @@ #include #include +#include #include +#include namespace sprout { namespace tpp { namespace detail { - template - struct all_of_impl; - template<> - struct all_of_impl<> - : public sprout::true_type + template + struct all_of_impl + : public std::tuple_element::type {}; - template<> - struct all_of_impl - : public sprout::true_type - {}; - template<> - struct all_of_impl - : public sprout::false_type - {}; - template - struct all_of_impl - : public sprout::integral_constant::value> - {}; - template - struct all_of_impl - : public sprout::false_type + template + struct all_of_impl + : public sprout::integral_constant< + bool, + sprout::tpp::detail::all_of_impl::value + && sprout::tpp::detail::all_of_impl::value + > {}; } // namespace detail // - // all_of_c - // - template - struct all_of_c - : public sprout::tpp::detail::all_of_impl - {}; - // // all_of // template struct all_of - : public sprout::tpp::all_of_c + : public sprout::tpp::detail::all_of_impl, 0, sizeof...(Types)> + {}; + template<> + struct all_of<> + : public sprout::true_type + {}; + // + // all_of_c + // + template + struct all_of_c + : public sprout::tpp::all_of...> {}; } // namespace tpp } // namespace sprout diff --git a/sprout/tpp/algorithm/any_of.hpp b/sprout/tpp/algorithm/any_of.hpp index 1900c7b9..4223cc6f 100644 --- a/sprout/tpp/algorithm/any_of.hpp +++ b/sprout/tpp/algorithm/any_of.hpp @@ -8,48 +8,45 @@ #ifndef SPROUT_TPP_ALGORITHM_ANY_OF_HPP #define SPROUT_TPP_ALGORITHM_ANY_OF_HPP +#include #include +#include #include +#include namespace sprout { namespace tpp { namespace detail { - template - struct any_of_impl; - template<> - struct any_of_impl<> - : public sprout::false_type + template + struct any_of_impl + : public std::tuple_element::type {}; - template<> - struct any_of_impl - : public sprout::true_type - {}; - template<> - struct any_of_impl - : public sprout::false_type - {}; - template - struct any_of_impl - : public sprout::true_type - {}; - template - struct any_of_impl - : public sprout::integral_constant::value> + template + struct any_of_impl + : public sprout::integral_constant< + bool, + sprout::tpp::detail::any_of_impl::value + || sprout::tpp::detail::any_of_impl::value + > {}; } // namespace detail // - // any_of_c - // - template - struct any_of_c - : public sprout::tpp::detail::any_of_impl - {}; - // // any_of // template struct any_of - : public sprout::tpp::any_of_c + : public sprout::tpp::detail::any_of_impl, 0, sizeof...(Types)> + {}; + template<> + struct any_of<> + : public sprout::false_type + {}; + // + // any_of_c + // + template + struct any_of_c + : public sprout::tpp::any_of...> {}; } // namespace tpp } // namespace sprout diff --git a/sprout/tpp/algorithm/none_of.hpp b/sprout/tpp/algorithm/none_of.hpp index 3aedfcab..ebd0d301 100644 --- a/sprout/tpp/algorithm/none_of.hpp +++ b/sprout/tpp/algorithm/none_of.hpp @@ -8,48 +8,45 @@ #ifndef SPROUT_TPP_ALGORITHM_NONE_OF_HPP #define SPROUT_TPP_ALGORITHM_NONE_OF_HPP +#include #include +#include #include +#include namespace sprout { namespace tpp { namespace detail { - template - struct none_of_impl; - template<> - struct none_of_impl<> - : public sprout::true_type + template + struct none_of_impl + : public sprout::integral_constant::type::value> {}; - template<> - struct none_of_impl - : public sprout::false_type - {}; - template<> - struct none_of_impl - : public sprout::true_type - {}; - template - struct none_of_impl - : public sprout::false_type - {}; - template - struct none_of_impl - : public sprout::integral_constant::value> + template + struct none_of_impl + : public sprout::integral_constant< + bool, + sprout::tpp::detail::none_of_impl::value + && sprout::tpp::detail::none_of_impl::value + > {}; } // namespace detail // - // none_of_c - // - template - struct none_of_c - : public sprout::tpp::detail::none_of_impl - {}; - // // none_of // template struct none_of - : public sprout::tpp::none_of_c + : public sprout::tpp::detail::none_of_impl, 0, sizeof...(Types)> + {}; + template<> + struct none_of<> + : public sprout::true_type + {}; + // + // none_of_c + // + template + struct none_of_c + : public sprout::tpp::none_of...> {}; } // namespace tpp } // namespace sprout diff --git a/sprout/tpp/algorithm/one_of.hpp b/sprout/tpp/algorithm/one_of.hpp index c62e558c..4202728b 100644 --- a/sprout/tpp/algorithm/one_of.hpp +++ b/sprout/tpp/algorithm/one_of.hpp @@ -8,50 +8,98 @@ #ifndef SPROUT_TPP_ALGORITHM_ONE_OF_HPP #define SPROUT_TPP_ALGORITHM_ONE_OF_HPP +#include #include -#include +#include #include +#include namespace sprout { namespace tpp { namespace detail { - template - struct one_of_impl; - template<> - struct one_of_impl<> - : public sprout::false_type + template + struct one_of_impl_1 + : public sprout::integral_constant::type::value> {}; - template<> - struct one_of_impl - : public sprout::true_type + template + struct one_of_impl_1 + : public sprout::integral_constant< + bool, + sprout::tpp::detail::one_of_impl_1::value + && sprout::tpp::detail::one_of_impl_1::value + > {}; - template<> - struct one_of_impl - : public sprout::false_type + + template + struct one_of_impl + : public std::tuple_element::type {}; - template - struct one_of_impl - : public sprout::tpp::none_of_c - {}; - template - struct one_of_impl - : public sprout::integral_constant::value> + template + struct one_of_impl + : public sprout::integral_constant< + bool, + sprout::tpp::detail::one_of_impl::value + ? sprout::tpp::detail::one_of_impl_1::value + : sprout::tpp::detail::one_of_impl::value + > {}; } // namespace detail // - // one_of_c - // - template - struct one_of_c - : public sprout::tpp::detail::one_of_impl - {}; - // // one_of // template struct one_of - : public sprout::tpp::one_of_c + : public sprout::tpp::detail::one_of_impl, 0, sizeof...(Types)> {}; + template<> + struct one_of<> + : public sprout::false_type + {}; + // + // one_of_c + // + template + struct one_of_c + : public sprout::tpp::one_of...> + {}; +// namespace detail { +// template +// struct one_of_impl; +// template<> +// struct one_of_impl<> +// : public sprout::false_type +// {}; +// template<> +// struct one_of_impl +// : public sprout::true_type +// {}; +// template<> +// struct one_of_impl +// : public sprout::false_type +// {}; +// template +// struct one_of_impl +// : public sprout::tpp::none_of_c +// {}; +// template +// struct one_of_impl +// : public sprout::integral_constant::value> +// {}; +// } // namespace detail +// // +// // one_of_c +// // +// template +// struct one_of_c +// : public sprout::tpp::detail::one_of_impl +// {}; +// // +// // one_of +// // +// template +// struct one_of +// : public sprout::tpp::one_of_c +// {}; } // namespace tpp } // namespace sprout diff --git a/sprout/tuple/tuple/get.hpp b/sprout/tuple/tuple/get.hpp index 3d74039d..17476bce 100644 --- a/sprout/tuple/tuple/get.hpp +++ b/sprout/tuple/tuple/get.hpp @@ -23,36 +23,23 @@ namespace sprout { namespace tuples { - namespace detail { - template - inline SPROUT_CONSTEXPR typename std::add_lvalue_reference::type - get_helper(sprout::tuples::detail::tuple_impl& t) SPROUT_NOEXCEPT { - return sprout::tuples::detail::tuple_impl::head(t); - } - template - inline SPROUT_CONSTEXPR typename std::add_lvalue_reference::type>::type - get_helper(sprout::tuples::detail::tuple_impl const& t) SPROUT_NOEXCEPT { - return sprout::tuples::detail::tuple_impl::head(t); - } - } // namespace detail // // tuple_get // template inline SPROUT_CONSTEXPR typename sprout::tuples::tuple_element >::type& tuple_get(sprout::tuples::tuple& t) SPROUT_NOEXCEPT { - return sprout::tuples::detail::get_helper(t); + return sprout::tuples::detail::tuple_access::template get(t); } template inline SPROUT_CONSTEXPR typename sprout::tuples::tuple_element >::type&& tuple_get(sprout::tuples::tuple&& t) SPROUT_NOEXCEPT { - typedef typename sprout::tuples::tuple_element >::type type; - return SPROUT_FORWARD(type, sprout::tuples::tuple_get(t)); + return sprout::tuples::detail::tuple_access::template get(sprout::move(t)); } template inline SPROUT_CONSTEXPR typename sprout::tuples::tuple_element >::type const& tuple_get(sprout::tuples::tuple const& t) SPROUT_NOEXCEPT { - return sprout::tuples::detail::get_helper(t); + return sprout::tuples::detail::tuple_access::template get(t); } } // namespace tuples diff --git a/sprout/tuple/tuple/tuple.hpp b/sprout/tuple/tuple/tuple.hpp index b4f4c685..8d08225a 100644 --- a/sprout/tuple/tuple/tuple.hpp +++ b/sprout/tuple/tuple/tuple.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,7 @@ namespace sprout { typename > inline SPROUT_CONSTEXPR sprout::tuples::tuple::tuple(sprout::pair const& t) - : impl_type(t.first, t.second) + : base_type(t.first, t.second) {} template template< @@ -34,7 +35,7 @@ namespace sprout { typename > inline SPROUT_CONSTEXPR sprout::tuples::tuple::tuple(sprout::pair&& t) - : impl_type(SPROUT_FORWARD(UType1, t.first), SPROUT_FORWARD(UType2, t.second)) + : base_type(SPROUT_FORWARD(UType1, t.first), SPROUT_FORWARD(UType2, t.second)) {} template @@ -43,7 +44,12 @@ namespace sprout { typename > inline SPROUT_CONSTEXPR sprout::tuples::tuple::tuple(sprout::tuples::flexibly_construct_t, sprout::pair const& t) - : impl_type(t.first, t.second) + : base_type( + sprout::tuples::flexibly_construct_t(), + sprout::index_range<0, 2>::make(), + sprout::index_range<2, sizeof...(Types)>::make(), + t.first, t.second + ) {} template template< @@ -51,7 +57,12 @@ namespace sprout { typename > inline SPROUT_CONSTEXPR sprout::tuples::tuple::tuple(sprout::tuples::flexibly_construct_t, sprout::pair&& t) - : impl_type(SPROUT_FORWARD(UType1, t.first), SPROUT_FORWARD(UType2, t.second)) + : base_type( + sprout::tuples::flexibly_construct_t(), + sprout::index_range<0, 2>::make(), + sprout::index_range<2, sizeof...(Types)>::make(), + SPROUT_FORWARD(UType1, t.first), SPROUT_FORWARD(UType2, t.second) + ) {} // tuple assignment template @@ -61,8 +72,8 @@ namespace sprout { > inline SPROUT_CXX14_CONSTEXPR sprout::tuples::tuple& sprout::tuples::tuple::operator=(sprout::pair const& rhs) { - sprout::tuples::detail::tuple_impl<0, Types...>::head(*this) = rhs.first; - sprout::tuples::detail::tuple_impl<1, Types...>::head(*this) = rhs.second; + base_type::template get<0>(*this) = rhs.first; + base_type::template get<1>(*this) = rhs.second; return *this; } template @@ -72,8 +83,8 @@ namespace sprout { > inline SPROUT_CXX14_CONSTEXPR sprout::tuples::tuple& sprout::tuples::tuple::operator=(sprout::pair&& rhs) { - sprout::tuples::detail::tuple_impl<0, Types...>::head(*this) = sprout::move(rhs.first); - sprout::tuples::detail::tuple_impl<1, Types...>::head(*this) = sprout::move(rhs.second); + base_type::template get<0>(*this) = sprout::move(rhs.first); + base_type::template get<1>(*this) = sprout::move(rhs.second); return *this; } } // namespace tuples diff --git a/sprout/tuple/tuple/tuple_decl.hpp b/sprout/tuple/tuple/tuple_decl.hpp index f9d648a7..d5b675e5 100644 --- a/sprout/tuple/tuple/tuple_decl.hpp +++ b/sprout/tuple/tuple/tuple_decl.hpp @@ -8,20 +8,22 @@ #ifndef SPROUT_TUPLE_TUPLE_TUPLE_DECL_HPP #define SPROUT_TUPLE_TUPLE_TUPLE_DECL_HPP -#include #include #include #include #include #include +#include #include #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -29,244 +31,170 @@ namespace sprout { namespace tuples { namespace detail { - template - struct dummy_integral_constant - : public sprout::integral_constant - {}; + template + class tuple_access; - template - class head_base; - // EBO disabled -// template -// class head_base -// : public Head -// { -// public: -// static SPROUT_CONSTEXPR Head& head(head_base& t) SPROUT_NOEXCEPT { -// return t; -// } -// static SPROUT_CONSTEXPR Head const& head(head_base const& t) SPROUT_NOEXCEPT { -// return t; -// } -// public: -// SPROUT_CONSTEXPR head_base() -// : Head() -// {} -// SPROUT_CONSTEXPR head_base(Head const& v) -// : Head(v) -// {} -// template -// explicit SPROUT_CONSTEXPR head_base(UHead&& v) -// : Head(SPROUT_FORWARD(UHead, v)) -// {} -// }; - template - class head_base { - public: - static SPROUT_CONSTEXPR Head& head(head_base& t) SPROUT_NOEXCEPT { - return t.head_; - } - static SPROUT_CONSTEXPR Head const& head(head_base const& t) SPROUT_NOEXCEPT { - return t.head_; - } - private: - Head head_; - public: - SPROUT_CONSTEXPR head_base() - : head_() - {} - SPROUT_CONSTEXPR head_base(Head const& v) - : head_(v) - {} - template - explicit SPROUT_CONSTEXPR head_base(UHead&& v) - : head_(SPROUT_FORWARD(UHead, v)) - {} - }; - template - class head_base { - public: - static SPROUT_CONSTEXPR Head& head(head_base& t) SPROUT_NOEXCEPT { - return t.head_; - } - static SPROUT_CONSTEXPR Head const& head(head_base const& t) SPROUT_NOEXCEPT { - return t.head_; - } - private: - Head head_; - public: - SPROUT_CONSTEXPR head_base() - : head_() - {} - SPROUT_CONSTEXPR head_base(Head const& v) - : head_(v) - {} - template - explicit SPROUT_CONSTEXPR head_base(UHead&& v) - : head_(SPROUT_FORWARD(UHead, v)) - {} - }; + struct from_tuple_construct_t {}; + struct few_construct_t {}; + struct excess_construct_t {}; - template - class tuple_impl; - template - class tuple_impl { + template + struct element_holder { public: - template - friend class tuple; - template - friend class sprout::tuples::detail::tuple_impl; + typedef typename IdentityType::type value_type; + private: + value_type value_; + public: + explicit SPROUT_CONSTEXPR element_holder() + : value_() + {} + element_holder(element_holder const&) = default; + element_holder(element_holder&&) = default; + template + explicit SPROUT_CONSTEXPR element_holder(T&& value) + : value_(SPROUT_FORWARD(T, value)) + {} protected: - SPROUT_CXX14_CONSTEXPR void swap(tuple_impl&) SPROUT_NOEXCEPT {} - public: - SPROUT_CONSTEXPR tuple_impl() SPROUT_DEFAULTED_DEFAULT_CONSTRUCTOR_DECL - template - explicit SPROUT_CONSTEXPR tuple_impl(UTypes&&...) SPROUT_NOEXCEPT {} - tuple_impl(tuple_impl const&) = default; - tuple_impl(tuple_impl&&) = default; - template - SPROUT_CONSTEXPR tuple_impl(tuple_impl const&) SPROUT_NOEXCEPT {} - template - SPROUT_CONSTEXPR tuple_impl(tuple_impl&&) SPROUT_NOEXCEPT {} - SPROUT_CXX14_CONSTEXPR tuple_impl& operator=(tuple_impl const&) SPROUT_NOEXCEPT { - return *this; + static SPROUT_CONSTEXPR value_type& + get(element_holder& t) { + return t.value_; } - SPROUT_CXX14_CONSTEXPR tuple_impl& operator=(tuple_impl&&) SPROUT_NOEXCEPT { - return *this; + static SPROUT_CONSTEXPR value_type&& + get(element_holder&& t) { + return sprout::move(t.value_); } - template - SPROUT_CXX14_CONSTEXPR tuple_impl& operator=(sprout::tuples::detail::tuple_impl const&) SPROUT_NOEXCEPT { - return *this; - } - template - SPROUT_CXX14_CONSTEXPR tuple_impl& operator=(sprout::tuples::detail::tuple_impl&&) SPROUT_NOEXCEPT { - return *this; + static SPROUT_CONSTEXPR value_type const& + get(element_holder const& t) { + return t.value_; } }; - template - class tuple_impl - : public sprout::tuples::detail::tuple_impl - , private sprout::tuples::detail::head_base::value> + + template + class tuple_base; + template + class tuple_base, Types...> + : public sprout::tuples::detail::element_holder >... { + template + friend class sprout::tuples::detail::tuple_base; + protected: + template + static IdentityType element_helper(sprout::tuples::detail::element_holder const&); + template + static sprout::detail::nil_base element_helper(...); + template + struct element + : public sprout::identity(std::declval()))>::type + {}; + struct size + : public sprout::integral_constant + {}; public: - template - friend class tuple; - template - friend class sprout::tuples::detail::tuple_impl; - public: - typedef sprout::tuples::detail::tuple_impl inherited_type; - typedef sprout::tuples::detail::head_base::value> base_type; - public: - static SPROUT_CONSTEXPR Head& head(tuple_impl& t) SPROUT_NOEXCEPT { - return base_type::head(t); - } - static SPROUT_CONSTEXPR Head const& head(tuple_impl const& t) SPROUT_NOEXCEPT { - return base_type::head(t); - } - static SPROUT_CONSTEXPR inherited_type& tail(tuple_impl& t) SPROUT_NOEXCEPT { - return t; - } - static SPROUT_CONSTEXPR inherited_type const& tail(tuple_impl const& t) SPROUT_NOEXCEPT { - return t; - } - public: - SPROUT_CXX14_CONSTEXPR void swap(tuple_impl& t) - SPROUT_NOEXCEPT_IF( - SPROUT_NOEXCEPT_EXPR(sprout::swap(head(std::declval()), head(t))) - && SPROUT_NOEXCEPT_EXPR(std::declval().swap(tail(t))) - ) - { - sprout::swap(head(*this), head(t)); - inherited_type::swap(tail(t)); - } - public: - SPROUT_CONSTEXPR tuple_impl() - : inherited_type() - , base_type() + SPROUT_CONSTEXPR tuple_base() + : sprout::tuples::detail::element_holder >()... {} - explicit SPROUT_CONSTEXPR tuple_impl(Head const& h, Tail const&... tail) - : inherited_type(tail...) - , base_type(h) - {} - template - explicit SPROUT_CONSTEXPR tuple_impl(UHead&& h, UTail&&... tail) - : inherited_type(SPROUT_FORWARD(UTail, tail)...) - , base_type(SPROUT_FORWARD(UHead, h)) - {} - tuple_impl(tuple_impl const&) = default; -#if SPROUT_GCC_IN_RANGE((4, 8, 0), (4, 8, 2)) - tuple_impl(tuple_impl&&) = default; -#else - SPROUT_CONSTEXPR tuple_impl(tuple_impl&& t) - SPROUT_NOEXCEPT_IF(std::is_nothrow_move_constructible::value && std::is_nothrow_move_constructible::value) - : inherited_type(sprout::move(tail(t))) - , base_type(SPROUT_FORWARD(Head, head(t))) - {} -#endif template - SPROUT_CONSTEXPR tuple_impl(tuple_impl const& t) - : inherited_type(sprout::tuples::detail::tuple_impl::tail(t)) - , base_type(sprout::tuples::detail::tuple_impl::head(t)) + explicit SPROUT_CONSTEXPR tuple_base(UTypes&&... args) + : sprout::tuples::detail::element_holder >(SPROUT_FORWARD(UTypes, args))... {} - template - SPROUT_CONSTEXPR tuple_impl(tuple_impl&& t) - : inherited_type(sprout::move(sprout::tuples::detail::tuple_impl::tail(t))) - , base_type(SPROUT_FORWARD(UHead, (sprout::tuples::detail::tuple_impl::head(t)))) + template + SPROUT_CONSTEXPR tuple_base(sprout::tuples::detail::from_tuple_construct_t, Tuple&& t) + : sprout::tuples::detail::element_holder >(std::decay::type::template get(SPROUT_FORWARD(Tuple, t)))... {} - SPROUT_CONSTEXPR tuple_impl(tuple_impl const&) - : inherited_type() - , base_type() + + template< + typename... UTypes, sprout::index_t... Is, sprout::index_t... Js, + typename sprout::enabler_if<(sizeof...(Types) == sizeof...(UTypes))>::type = sprout::enabler + > + explicit SPROUT_CONSTEXPR tuple_base(sprout::tuples::flexibly_construct_t, sprout::index_tuple, sprout::index_tuple, UTypes&&... args) + : sprout::tuples::detail::element_holder >(SPROUT_FORWARD(UTypes, args))... {} - SPROUT_CONSTEXPR tuple_impl(tuple_impl&&) - : inherited_type() - , base_type() + template< + typename... UTypes, sprout::index_t... Is, sprout::index_t... Js, + typename sprout::enabler_if<(sizeof...(Types) > sizeof...(UTypes))>::type = sprout::enabler + > + explicit SPROUT_CONSTEXPR tuple_base(sprout::tuples::flexibly_construct_t, sprout::index_tuple, sprout::index_tuple, UTypes&&... args) + : sprout::tuples::detail::element_holder::type> >(SPROUT_FORWARD(UTypes, args))... + , sprout::tuples::detail::element_holder::type> >()... {} - SPROUT_CXX14_CONSTEXPR tuple_impl& operator=(tuple_impl const& t) { - head(*this) = head(t); - tail(*this) = tail(t); - return *this; + template< + typename... UTypes, sprout::index_t... Is, sprout::index_t... Js, + typename sprout::enabler_if<(sizeof...(Types) < sizeof...(UTypes))>::type = sprout::enabler + > + explicit SPROUT_CONSTEXPR tuple_base(sprout::tuples::flexibly_construct_t, sprout::index_tuple, sprout::index_tuple, UTypes&&... args) + : sprout::tuples::detail::element_holder >(sprout::pack_get(SPROUT_FORWARD(UTypes, args)...))... + {} + + template< + typename Tuple, sprout::index_t... Is, sprout::index_t... Js, + typename sprout::enabler_if<(sizeof...(Types) == std::decay::type::size::value)>::type = sprout::enabler + > + explicit SPROUT_CONSTEXPR tuple_base(sprout::tuples::detail::from_tuple_construct_t, sprout::tuples::flexibly_construct_t, sprout::index_tuple, sprout::index_tuple, Tuple&& t) + : sprout::tuples::detail::element_holder >(std::decay::type::template get(SPROUT_FORWARD(Tuple, t)))... + {} + template< + typename Tuple, sprout::index_t... Is, sprout::index_t... Js, + typename sprout::enabler_if<(sizeof...(Types) > std::decay::type::size::value)>::type = sprout::enabler + > + explicit SPROUT_CONSTEXPR tuple_base(sprout::tuples::detail::from_tuple_construct_t, sprout::tuples::flexibly_construct_t, sprout::index_tuple, sprout::index_tuple, Tuple&& t) + : sprout::tuples::detail::element_holder::type> >(std::decay::type::template get(SPROUT_FORWARD(Tuple, t)))... + , sprout::tuples::detail::element_holder::type> >()... + {} + template< + typename Tuple, sprout::index_t... Is, sprout::index_t... Js, + typename sprout::enabler_if<(sizeof...(Types) < std::decay::type::size::value)>::type = sprout::enabler + > + explicit SPROUT_CONSTEXPR tuple_base(sprout::tuples::detail::from_tuple_construct_t, sprout::tuples::flexibly_construct_t, sprout::index_tuple, sprout::index_tuple, Tuple&& t) + : sprout::tuples::detail::element_holder >(std::decay::type::template get(SPROUT_FORWARD(Tuple, t)))... + {} + private: + template + static SPROUT_CONSTEXPR typename element::type& + get_impl(sprout::tuples::detail::element_holder& value) { + return sprout::tuples::detail::element_holder::get(value); } - SPROUT_CXX14_CONSTEXPR tuple_impl& operator=(tuple_impl&& t) - SPROUT_NOEXCEPT_IF(std::is_nothrow_move_assignable::value && std::is_nothrow_move_assignable::value) - { - head(*this) = SPROUT_FORWARD(Head, head(t)); - tail(*this) = sprout::move(tail(t)); - return *this; + template + static SPROUT_CONSTEXPR typename element::type&& + get_impl(sprout::tuples::detail::element_holder&& value) { + return sprout::tuples::detail::element_holder::get(sprout::move(value)); } - template - SPROUT_CXX14_CONSTEXPR tuple_impl& operator=(sprout::tuples::detail::tuple_impl const& t) { - head(*this) = sprout::tuples::detail::tuple_impl::head(t); - tail(*this) = sprout::tuples::detail::tuple_impl::tail(t); - return *this; + template + static SPROUT_CONSTEXPR typename element::type const& + get_impl(sprout::tuples::detail::element_holder const& value) { + return sprout::tuples::detail::element_holder::get(value); } - template - SPROUT_CXX14_CONSTEXPR tuple_impl& operator=(sprout::tuples::detail::tuple_impl&& t) { - head(*this) = SPROUT_FORWARD(UHead, (sprout::tuples::detail::tuple_impl::head(t))); - tail(*this) = sprout::move(sprout::tuples::detail::tuple_impl::tail(t)); - return *this; + protected: + template + static SPROUT_CONSTEXPR typename element::type& + get(tuple_base& t) { + return get_impl(t); } - SPROUT_CXX14_CONSTEXPR tuple_impl& operator=(sprout::tuples::detail::tuple_impl const&) { - *this = sprout::move(tuple_impl()); - return *this; + template + static SPROUT_CONSTEXPR typename element::type&& + get(tuple_base&& t) { + return get_impl(sprout::move(t)); } - SPROUT_CXX14_CONSTEXPR tuple_impl& operator=(sprout::tuples::detail::tuple_impl&&) { - *this = sprout::move(tuple_impl()); - return *this; + template + static SPROUT_CONSTEXPR typename element::type const& + get(tuple_base const& t) { + return get_impl(t); } }; } // namespace detail - // - // tuple - // template class tuple - : public sprout::tuples::detail::tuple_impl<0, Types...> + : public sprout::tuples::detail::tuple_base::type, Types...> { + template + friend class sprout::tuples::tuple; + template + friend class sprout::tuples::detail::tuple_access; private: - typedef sprout::tuples::detail::tuple_impl<0, Types...> impl_type; + typedef typename sprout::make_index_tuple::type index_tuple_type; + typedef sprout::tuples::detail::tuple_base base_type; private: - template + template struct is_flexibly_convert_constructible_impl; template struct is_flexibly_convert_constructible_impl, Utypes...> @@ -278,7 +206,7 @@ namespace sprout { > {}; - template + template struct is_flexibly_assignable_impl; template struct is_flexibly_assignable_impl, Utypes...> @@ -353,13 +281,30 @@ namespace sprout { struct is_clvref_fixedly_assignable : public is_fixedly_assignable {}; + private: + template + SPROUT_CXX14_CONSTEXPR void + swap_impl(tuple& other, sprout::index_tuple) { + sprout::eat((sprout::swap(base_type::template get(*this), base_type::template get(other)), 0)...); + } + template + SPROUT_CXX14_CONSTEXPR void + assign(Tuple&& t) { + assign_impl(SPROUT_FORWARD(Tuple, t), index_tuple_type()); + } + template + SPROUT_CXX14_CONSTEXPR void + assign_impl(Tuple&& t, sprout::index_tuple) { + typedef typename std::decay::type type; + sprout::eat((sprout::eat(base_type::template get(*this) = sprout::move(type::template get(SPROUT_FORWARD(Tuple, t)))), 0)...); + } public: // tuple construction SPROUT_CONSTEXPR tuple() - : impl_type() + : base_type() {} explicit SPROUT_CONSTEXPR tuple(Types const&... elements) - : impl_type(elements...) + : base_type(elements...) {} template< typename... UTypes, @@ -368,7 +313,7 @@ namespace sprout { >::type > explicit SPROUT_CONSTEXPR tuple(UTypes&&... elements) - : impl_type(SPROUT_FORWARD(UTypes, elements)...) + : base_type(SPROUT_FORWARD(UTypes, elements)...) {} tuple(tuple const&) = default; tuple(tuple&&) = default; @@ -379,7 +324,7 @@ namespace sprout { >::type > SPROUT_CONSTEXPR tuple(sprout::tuples::tuple const& t) - : impl_type(static_cast const&>(t)) + : base_type(sprout::tuples::detail::from_tuple_construct_t(), t) {} template< typename... UTypes, @@ -388,7 +333,7 @@ namespace sprout { >::type > SPROUT_CONSTEXPR tuple(sprout::tuples::tuple&& t) - : impl_type(static_cast&&>(t)) + : base_type(sprout::tuples::detail::from_tuple_construct_t(), sprout::move(t)) {} template< typename UType1, typename UType2, @@ -404,7 +349,6 @@ namespace sprout { >::type > SPROUT_CONSTEXPR tuple(sprout::pair&& t); - template< typename... UTypes, typename = typename std::enable_if< @@ -412,7 +356,12 @@ namespace sprout { >::type > explicit SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, UTypes&&... elements) - : impl_type(SPROUT_FORWARD(UTypes, elements)...) + : base_type( + sprout::tuples::flexibly_construct_t(), + sprout::index_range<0, sizeof...(UTypes)>::make(), + sprout::index_range::make(), + SPROUT_FORWARD(UTypes, elements)... + ) {} template< typename... UTypes, @@ -421,8 +370,14 @@ namespace sprout { >::type > SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, sprout::tuples::tuple const& t) - : impl_type(static_cast const&>(t)) + : base_type( + sprout::tuples::detail::from_tuple_construct_t(), sprout::tuples::flexibly_construct_t(), + sprout::index_range<0, sizeof...(UTypes)>::make(), + sprout::index_range::make(), + t + ) {} + template< typename... UTypes, typename = typename std::enable_if< @@ -430,7 +385,12 @@ namespace sprout { >::type > SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, sprout::tuples::tuple&& t) - : impl_type(static_cast&&>(t)) + : base_type( + sprout::tuples::detail::from_tuple_construct_t(), sprout::tuples::flexibly_construct_t(), + sprout::index_range<0, sizeof...(UTypes)>::make(), + sprout::index_range::make(), + sprout::move(t) + ) {} template< typename UType1, typename UType2, @@ -447,14 +407,16 @@ namespace sprout { > SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, sprout::pair&& t); // tuple assignment - SPROUT_CXX14_CONSTEXPR tuple& operator=(tuple const& rhs) { - static_cast(*this) = rhs; + SPROUT_CXX14_CONSTEXPR tuple& + operator=(tuple const& rhs) { + assign(rhs); return *this; } - SPROUT_CXX14_CONSTEXPR tuple& operator=(tuple&& rhs) + SPROUT_CXX14_CONSTEXPR tuple& + operator=(tuple&& rhs) SPROUT_NOEXCEPT_IF(sprout::tpp::all_of...>::value) { - static_cast(*this) = sprout::move(rhs); + assign(sprout::move(rhs)); return *this; } template< @@ -463,8 +425,9 @@ namespace sprout { sizeof...(Types) == sizeof...(UTypes) && sprout::tpp::all_of...>::value >::type > - SPROUT_CXX14_CONSTEXPR tuple& operator=(sprout::tuples::tuple const& rhs) { - static_cast(*this) = rhs; + SPROUT_CXX14_CONSTEXPR tuple& + operator=(sprout::tuples::tuple const& rhs) { + assign(rhs); return *this; } template< @@ -473,8 +436,9 @@ namespace sprout { sizeof...(Types) == sizeof...(UTypes) && sprout::tpp::all_of...>::value >::type > - SPROUT_CXX14_CONSTEXPR tuple& operator=(sprout::tuples::tuple&& rhs) { - static_cast(*this) = sprout::move(rhs); + SPROUT_CXX14_CONSTEXPR tuple& + operator=(sprout::tuples::tuple&& rhs) { + assign(sprout::move(rhs)); return *this; } template< @@ -492,29 +456,37 @@ namespace sprout { > SPROUT_CXX14_CONSTEXPR tuple& operator=(sprout::pair&& rhs); // tuple swap - SPROUT_CXX14_CONSTEXPR void swap(tuple& other) + SPROUT_CXX14_CONSTEXPR void + swap(tuple& other) SPROUT_NOEXCEPT_IF(sprout::tpp::all_of_c(), std::declval()))...>::value) { - impl_type::swap(other); + swap_impl(other, index_tuple_type()); } }; template<> class tuple<> { + template + friend class sprout::tuples::detail::tuple_access; + protected: + template + struct element + : public sprout::detail::nil_base + {}; public: // tuple construction SPROUT_CONSTEXPR tuple() SPROUT_DEFAULTED_DEFAULT_CONSTRUCTOR_DECL tuple(tuple const&) = default; tuple(tuple&&) = default; template - explicit SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, UTypes&&...) {} + explicit SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, UTypes&&...) SPROUT_NOEXCEPT {} template - SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, sprout::tuples::tuple const&) {} + SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, sprout::tuples::tuple const&) SPROUT_NOEXCEPT {} template - SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, sprout::tuples::tuple&&) {} + SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, sprout::tuples::tuple&&) SPROUT_NOEXCEPT {} template - SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, sprout::pair const&) {} + SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, sprout::pair const&) SPROUT_NOEXCEPT {} template - SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, sprout::pair&&) {} + SPROUT_CONSTEXPR tuple(sprout::tuples::flexibly_construct_t, sprout::pair&&) SPROUT_NOEXCEPT {} // tuple swap SPROUT_CXX14_CONSTEXPR void swap(tuple&) SPROUT_NOEXCEPT {} }; @@ -529,6 +501,36 @@ namespace sprout { { lhs.swap(rhs); } + + namespace detail { + template + class tuple_access { + public: + template + struct element + : public sprout::tuples::tuple::template element + {}; + struct size + : public sprout::integral_constant + {}; + public: + template + static SPROUT_CONSTEXPR typename element::type& + get(sprout::tuples::tuple& t) { + return sprout::tuples::tuple::template get(t); + } + template + static SPROUT_CONSTEXPR typename element::type&& + get(sprout::tuples::tuple&& t) { + return sprout::tuples::tuple::template get(sprout::move(t)); + } + template + static SPROUT_CONSTEXPR typename element::type const& + get(sprout::tuples::tuple const& t) { + return sprout::tuples::tuple::template get(t); + } + }; + } // namespace detail } // namespace tuples using sprout::tuples::tuple; @@ -553,7 +555,8 @@ namespace std { // template struct tuple_element > - : public sprout::pack_element +// : public sprout::pack_element + : public sprout::tuples::detail::tuple_access::template element {}; #if defined(__clang__) # pragma clang diagnostic pop diff --git a/sprout/type/type_tuple.hpp b/sprout/type/type_tuple.hpp index 354197d1..6680051c 100644 --- a/sprout/type/type_tuple.hpp +++ b/sprout/type/type_tuple.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -25,6 +26,11 @@ namespace sprout { typedef type_tuple type; typedef sprout::types::index_iterator begin; typedef sprout::types::index_iterator end; + public: + template + struct apply + : public sprout::identity > + {}; public: SPROUT_STATIC_CONSTEXPR std::size_t static_size = sizeof...(Types); }; diff --git a/sprout/utility/eat.hpp b/sprout/utility/eat.hpp new file mode 100644 index 00000000..80e40223 --- /dev/null +++ b/sprout/utility/eat.hpp @@ -0,0 +1,21 @@ +/*============================================================================= + 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_UTILITY_EAT_HPP +#define SPROUT_UTILITY_EAT_HPP + +#include + +namespace sprout { + // + // eat + // + inline SPROUT_CXX14_CONSTEXPR void + eat(...) SPROUT_NOEXCEPT {} +} // namespace sprout + +#endif // #ifndef SPROUT_UTILITY_EAT_HPP diff --git a/sprout/utility/operation.hpp b/sprout/utility/operation.hpp index 44261a3a..950537ba 100644 --- a/sprout/utility/operation.hpp +++ b/sprout/utility/operation.hpp @@ -15,5 +15,6 @@ #include #include #include +#include #endif // #ifndef SPROUT_UTILITY_OPERATION_HPP