123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- /*!
- @file
- Defines `boost::hana::tuple`.
- @copyright Louis Dionne 2013-2016
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
- */
- #ifndef BOOST_HANA_TUPLE_HPP
- #define BOOST_HANA_TUPLE_HPP
- #include <boost/hana/fwd/tuple.hpp>
- #include <boost/hana/basic_tuple.hpp>
- #include <boost/hana/bool.hpp>
- #include <boost/hana/config.hpp>
- #include <boost/hana/detail/decay.hpp>
- #include <boost/hana/detail/fast_and.hpp>
- #include <boost/hana/detail/index_if.hpp>
- #include <boost/hana/detail/intrinsics.hpp>
- #include <boost/hana/detail/operators/adl.hpp>
- #include <boost/hana/detail/operators/comparable.hpp>
- #include <boost/hana/detail/operators/iterable.hpp>
- #include <boost/hana/detail/operators/monad.hpp>
- #include <boost/hana/detail/operators/orderable.hpp>
- #include <boost/hana/fwd/at.hpp>
- #include <boost/hana/fwd/core/make.hpp>
- #include <boost/hana/fwd/drop_front.hpp>
- #include <boost/hana/fwd/find_if.hpp>
- #include <boost/hana/fwd/is_empty.hpp>
- #include <boost/hana/fwd/length.hpp>
- #include <boost/hana/fwd/optional.hpp>
- #include <boost/hana/fwd/unpack.hpp>
- #include <boost/hana/type.hpp> // required by fwd decl of tuple_t
- #include <cstddef>
- #include <type_traits>
- #include <utility>
- BOOST_HANA_NAMESPACE_BEGIN
- namespace detail {
- template <typename Xs, typename Ys, std::size_t ...n>
- constexpr void assign(Xs& xs, Ys&& ys, std::index_sequence<n...>) {
- int sequence[] = {int{}, ((void)(
- hana::get_impl<n>(xs) = hana::get_impl<n>(static_cast<Ys&&>(ys))
- ), int{})...};
- (void)sequence;
- }
- struct from_index_sequence_t { };
- }
- //////////////////////////////////////////////////////////////////////////
- // tuple
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct tuple<>
- : detail::operators::adl<tuple<>>
- , detail::iterable_operators<tuple<>>
- {
- constexpr tuple() { }
- using hana_tag = tuple_tag;
- };
- template <typename ...Xn>
- struct tuple
- : detail::operators::adl<tuple<Xn...>>
- , detail::iterable_operators<tuple<Xn...>>
- {
- basic_tuple<Xn...> storage_;
- using hana_tag = tuple_tag;
- private:
- template <typename Other, std::size_t ...n>
- explicit constexpr tuple(detail::from_index_sequence_t, std::index_sequence<n...>, Other&& other)
- : storage_(hana::get_impl<n>(static_cast<Other&&>(other))...)
- { }
- public:
- template <typename ...dummy, typename = typename std::enable_if<
- detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, dummy...)...>::value
- >::type>
- constexpr tuple()
- : storage_()
- { }
- template <typename ...dummy, typename = typename std::enable_if<
- detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
- >::type>
- constexpr tuple(Xn const& ...xn)
- : storage_(xn...)
- { }
- template <typename ...Yn, typename = typename std::enable_if<
- detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
- >::type>
- constexpr tuple(Yn&& ...yn)
- : storage_(static_cast<Yn&&>(yn)...)
- { }
- template <typename ...Yn, typename = typename std::enable_if<
- detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn const&)...>::value
- >::type>
- constexpr tuple(tuple<Yn...> const& other)
- : tuple(detail::from_index_sequence_t{},
- std::make_index_sequence<sizeof...(Xn)>{},
- other.storage_)
- { }
- template <typename ...Yn, typename = typename std::enable_if<
- detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
- >::type>
- constexpr tuple(tuple<Yn...>&& other)
- : tuple(detail::from_index_sequence_t{},
- std::make_index_sequence<sizeof...(Xn)>{},
- static_cast<tuple<Yn...>&&>(other).storage_)
- { }
- // The three following constructors are required to make sure that
- // the tuple(Yn&&...) constructor is _not_ preferred over the copy
- // constructor for unary tuples containing a type that is constructible
- // from tuple<...>. See test/tuple/trap_construct.cpp
- template <typename ...dummy, typename = typename std::enable_if<
- detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
- >::type>
- constexpr tuple(tuple const& other)
- : tuple(detail::from_index_sequence_t{},
- std::make_index_sequence<sizeof...(Xn)>{},
- other.storage_)
- { }
- template <typename ...dummy, typename = typename std::enable_if<
- detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
- >::type>
- constexpr tuple(tuple& other)
- : tuple(const_cast<tuple const&>(other))
- { }
- template <typename ...dummy, typename = typename std::enable_if<
- detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn&&, dummy...)...>::value
- >::type>
- constexpr tuple(tuple&& other)
- : tuple(detail::from_index_sequence_t{},
- std::make_index_sequence<sizeof...(Xn)>{},
- static_cast<tuple&&>(other).storage_)
- { }
- template <typename ...Yn, typename = typename std::enable_if<
- detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn const&)...>::value
- >::type>
- constexpr tuple& operator=(tuple<Yn...> const& other) {
- detail::assign(this->storage_, other.storage_,
- std::make_index_sequence<sizeof...(Xn)>{});
- return *this;
- }
- template <typename ...Yn, typename = typename std::enable_if<
- detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn&&)...>::value
- >::type>
- constexpr tuple& operator=(tuple<Yn...>&& other) {
- detail::assign(this->storage_, static_cast<tuple<Yn...>&&>(other).storage_,
- std::make_index_sequence<sizeof...(Xn)>{});
- return *this;
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Operators
- //////////////////////////////////////////////////////////////////////////
- namespace detail {
- template <>
- struct comparable_operators<tuple_tag> {
- static constexpr bool value = true;
- };
- template <>
- struct orderable_operators<tuple_tag> {
- static constexpr bool value = true;
- };
- template <>
- struct monad_operators<tuple_tag> {
- static constexpr bool value = true;
- };
- }
- //////////////////////////////////////////////////////////////////////////
- // Foldable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct unpack_impl<tuple_tag> {
- template <typename F>
- static constexpr decltype(auto) apply(tuple<>&&, F&& f)
- { return static_cast<F&&>(f)(); }
- template <typename F>
- static constexpr decltype(auto) apply(tuple<>&, F&& f)
- { return static_cast<F&&>(f)(); }
- template <typename F>
- static constexpr decltype(auto) apply(tuple<> const&, F&& f)
- { return static_cast<F&&>(f)(); }
- template <typename Xs, typename F>
- static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
- return hana::unpack(static_cast<Xs&&>(xs).storage_, static_cast<F&&>(f));
- }
- };
- template <>
- struct length_impl<tuple_tag> {
- template <typename ...Xs>
- static constexpr auto apply(tuple<Xs...> const&)
- { return hana::size_c<sizeof...(Xs)>; }
- };
- //////////////////////////////////////////////////////////////////////////
- // Iterable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct at_impl<tuple_tag> {
- template <typename Xs, typename N>
- static constexpr decltype(auto) apply(Xs&& xs, N const&) {
- constexpr std::size_t index = N::value;
- return hana::get_impl<index>(static_cast<Xs&&>(xs).storage_);
- }
- };
- template <>
- struct drop_front_impl<tuple_tag> {
- template <std::size_t N, typename Xs, std::size_t ...i>
- static constexpr auto helper(Xs&& xs, std::index_sequence<i...>) {
- return hana::make<tuple_tag>(hana::at_c<i+N>(static_cast<Xs&&>(xs))...);
- }
- template <typename Xs, typename N>
- static constexpr auto apply(Xs&& xs, N const&) {
- constexpr std::size_t len = decltype(hana::length(xs))::value;
- return helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence<
- N::value < len ? len - N::value : 0
- >{});
- }
- };
- template <>
- struct is_empty_impl<tuple_tag> {
- template <typename ...Xs>
- static constexpr auto apply(tuple<Xs...> const&)
- { return hana::bool_c<sizeof...(Xs) == 0>; }
- };
- // compile-time optimizations (to reduce the # of function instantiations)
- template <std::size_t n, typename ...Xs>
- constexpr decltype(auto) at_c(tuple<Xs...> const& xs) {
- return hana::get_impl<n>(xs.storage_);
- }
- template <std::size_t n, typename ...Xs>
- constexpr decltype(auto) at_c(tuple<Xs...>& xs) {
- return hana::get_impl<n>(xs.storage_);
- }
- template <std::size_t n, typename ...Xs>
- constexpr decltype(auto) at_c(tuple<Xs...>&& xs) {
- return hana::get_impl<n>(static_cast<tuple<Xs...>&&>(xs).storage_);
- }
- //////////////////////////////////////////////////////////////////////////
- // Sequence
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct Sequence<tuple_tag> {
- static constexpr bool value = true;
- };
- template <>
- struct make_impl<tuple_tag> {
- template <typename ...Xs>
- static constexpr
- tuple<typename detail::decay<Xs>::type...> apply(Xs&& ...xs)
- { return {static_cast<Xs&&>(xs)...}; }
- };
- template <>
- struct find_if_impl<tuple_tag> {
- template <std::size_t index, typename Xs>
- static constexpr auto helper(Xs&&, hana::true_) {
- return hana::nothing;
- }
- template <std::size_t index, typename Xs>
- static constexpr auto helper(Xs&& xs, hana::false_) {
- return hana::just(hana::at_c<index>(static_cast<Xs&&>(xs)));
- }
- template <typename Xs, typename Pred>
- static constexpr auto apply(Xs&& xs, Pred&&) {
- using Pack = typename detail::make_pack<Xs>::type;
- constexpr std::size_t index = detail::index_if<Pred&&, Pack>::value;
- constexpr std::size_t len = Pack::length;
- return helper<index>(static_cast<Xs&&>(xs), hana::bool_c<index == len>);
- }
- };
- BOOST_HANA_NAMESPACE_END
- #endif // !BOOST_HANA_TUPLE_HPP
|