diff options
Diffstat (limited to 'boost/hana/basic_tuple.hpp')
-rw-r--r-- | boost/hana/basic_tuple.hpp | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/boost/hana/basic_tuple.hpp b/boost/hana/basic_tuple.hpp new file mode 100644 index 0000000000..685011e10c --- /dev/null +++ b/boost/hana/basic_tuple.hpp @@ -0,0 +1,299 @@ +/*! +@file +Defines `boost::hana::basic_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_BASIC_TUPLE_HPP +#define BOOST_HANA_BASIC_TUPLE_HPP + +#include <boost/hana/fwd/basic_tuple.hpp> + +#include <boost/hana/config.hpp> +#include <boost/hana/detail/decay.hpp> +#include <boost/hana/detail/intrinsics.hpp> +#include <boost/hana/fwd/at.hpp> +#include <boost/hana/fwd/bool.hpp> +#include <boost/hana/fwd/concept/sequence.hpp> +#include <boost/hana/fwd/core/make.hpp> +#include <boost/hana/fwd/core/tag_of.hpp> +#include <boost/hana/fwd/drop_front.hpp> +#include <boost/hana/fwd/is_empty.hpp> +#include <boost/hana/fwd/transform.hpp> +#include <boost/hana/fwd/unpack.hpp> + +#if 0 //! @todo Until we strip down headers, this includes too much +#include <boost/hana/fwd/integral_constant.hpp> +#include <boost/hana/fwd/length.hpp> +#endif + +#include <cstddef> +#include <type_traits> +#include <utility> + + +BOOST_HANA_NAMESPACE_BEGIN + namespace detail { + ////////////////////////////////////////////////////////////////////// + // elt<n, Xn> + // + // `elt` stands for `tuple_element`; the name is compressed to reduce + // symbol lengths. + // + // Wrapper holding the actual elements of a tuple. It takes care of + // optimizing the storage for empty types. + // + // When available, we use compiler intrinsics to reduce the number + // of instantiations. + ////////////////////////////////////////////////////////////////////// + template <std::size_t n, typename Xn, bool = + BOOST_HANA_TT_IS_EMPTY(Xn) && !BOOST_HANA_TT_IS_FINAL(Xn) + > + struct elt; + + // Specialize storage for empty types + template <std::size_t n, typename Xn> + struct elt<n, Xn, true> : Xn { + constexpr elt() = default; + + template <typename Yn> + explicit constexpr elt(Yn&& yn) + : Xn(static_cast<Yn&&>(yn)) + { } + }; + + // Specialize storage for non-empty types + template <std::size_t n, typename Xn> + struct elt<n, Xn, false> { + constexpr elt() = default; + + template <typename Yn> + explicit constexpr elt(Yn&& yn) + : data_(static_cast<Yn&&>(yn)) + { } + + Xn data_; + }; + } + + ////////////////////////////////////////////////////////////////////////// + // get_impl + ////////////////////////////////////////////////////////////////////////// + template <std::size_t n, typename Xn> + constexpr Xn const& get_impl(detail::elt<n, Xn, true> const& xn) + { return xn; } + + template <std::size_t n, typename Xn> + constexpr Xn& get_impl(detail::elt<n, Xn, true>& xn) + { return xn; } + + template <std::size_t n, typename Xn> + constexpr Xn&& get_impl(detail::elt<n, Xn, true>&& xn) + { return static_cast<Xn&&>(xn); } + + + template <std::size_t n, typename Xn> + constexpr Xn const& get_impl(detail::elt<n, Xn, false> const& xn) + { return xn.data_; } + + template <std::size_t n, typename Xn> + constexpr Xn& get_impl(detail::elt<n, Xn, false>& xn) + { return xn.data_; } + + template <std::size_t n, typename Xn> + constexpr Xn&& get_impl(detail::elt<n, Xn, false>&& xn) + { return static_cast<Xn&&>(xn.data_); } + + namespace detail { + ////////////////////////////////////////////////////////////////////// + // basic_tuple_impl<n, Xn> + ////////////////////////////////////////////////////////////////////// + struct from_other { }; + + template <typename Indices, typename ...Xn> + struct basic_tuple_impl; + + template <std::size_t ...n, typename ...Xn> + struct basic_tuple_impl<std::index_sequence<n...>, Xn...> + : detail::elt<n, Xn>... + { + static constexpr std::size_t size_ = sizeof...(Xn); + + constexpr basic_tuple_impl() = default; + + template <typename Other> + explicit constexpr basic_tuple_impl(detail::from_other, Other&& other) + : detail::elt<n, Xn>(get_impl<n>(static_cast<Other&&>(other)))... + { } + + template <typename ...Yn> + explicit constexpr basic_tuple_impl(Yn&& ...yn) + : detail::elt<n, Xn>(static_cast<Yn&&>(yn))... + { } + }; + } + + ////////////////////////////////////////////////////////////////////////// + // basic_tuple + ////////////////////////////////////////////////////////////////////////// + //! @cond + template <typename ...Xn> + struct basic_tuple final + : detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...> + { + using Base = detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>; + + constexpr basic_tuple() = default; + + // copy constructor + template <typename Other, typename = typename std::enable_if< + std::is_same<typename std::decay<Other>::type, basic_tuple>::value + >::type> + constexpr basic_tuple(Other&& other) + : Base(detail::from_other{}, static_cast<Other&&>(other)) + { } + + template <typename ...Yn> + explicit constexpr basic_tuple(Yn&& ...yn) + : Base(static_cast<Yn&&>(yn)...) + { } + }; + //! @endcond + + template <typename ...Xn> + struct tag_of<basic_tuple<Xn...>> { + using type = basic_tuple_tag; + }; + + ////////////////////////////////////////////////////////////////////////// + // Foldable + ////////////////////////////////////////////////////////////////////////// + template <> + struct unpack_impl<basic_tuple_tag> { + template <std::size_t ...i, typename ...Xn, typename F> + static constexpr decltype(auto) + apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F&& f) { + return static_cast<F&&>(f)( + get_impl<i>(static_cast<detail::elt<i, Xn> const&>(xs))... + ); + } + + template <std::size_t ...i, typename ...Xn, typename F> + static constexpr decltype(auto) + apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F&& f) { + return static_cast<F&&>(f)( + get_impl<i>(static_cast<detail::elt<i, Xn>&>(xs))... + ); + } + + template <std::size_t ...i, typename ...Xn, typename F> + static constexpr decltype(auto) + apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F&& f) { + return static_cast<F&&>(f)( + get_impl<i>(static_cast<detail::elt<i, Xn>&&>(xs))... + ); + } + }; + + ////////////////////////////////////////////////////////////////////////// + // Functor + ////////////////////////////////////////////////////////////////////////// + template <> + struct transform_impl<basic_tuple_tag> { + template <std::size_t ...i, typename ...Xn, typename F> + static constexpr auto + apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F const& f) { + return hana::make_basic_tuple( + f(get_impl<i>(static_cast<detail::elt<i, Xn> const&>(xs)))... + ); + } + + template <std::size_t ...i, typename ...Xn, typename F> + static constexpr auto + apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F const& f) { + return hana::make_basic_tuple( + f(get_impl<i>(static_cast<detail::elt<i, Xn>&>(xs)))... + ); + } + + template <std::size_t ...i, typename ...Xn, typename F> + static constexpr auto + apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F const& f) { + return hana::make_basic_tuple( + f(get_impl<i>(static_cast<detail::elt<i, Xn>&&>(xs)))... + ); + } + }; + + ////////////////////////////////////////////////////////////////////////// + // Iterable + ////////////////////////////////////////////////////////////////////////// + template <> + struct at_impl<basic_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)); + } + }; + + template <> + struct drop_front_impl<basic_tuple_tag> { + template <std::size_t N, typename Xs, std::size_t ...i> + static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) { + return hana::make_basic_tuple(hana::get_impl<i+N>(static_cast<Xs&&>(xs))...); + } + + template <typename Xs, typename N> + static constexpr auto apply(Xs&& xs, N const&) { + constexpr std::size_t len = detail::decay<Xs>::type::size_; + return drop_front_helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence< + N::value < len ? len - N::value : 0 + >{}); + } + }; + + template <> + struct is_empty_impl<basic_tuple_tag> { + template <typename ...Xs> + static constexpr auto apply(basic_tuple<Xs...> const&) + { return hana::bool_c<sizeof...(Xs) == 0>; } + }; + + ////////////////////////////////////////////////////////////////////////// + // Sequence + ////////////////////////////////////////////////////////////////////////// + template <> + struct Sequence<basic_tuple_tag> { + static constexpr bool value = true; + }; + + template <> + struct make_impl<basic_tuple_tag> { + template <typename ...Xn> + static constexpr basic_tuple<typename detail::decay<Xn>::type...> + apply(Xn&& ...xn) { + return basic_tuple<typename detail::decay<Xn>::type...>{ + static_cast<Xn&&>(xn)... + }; + } + }; + +#if 0 + ////////////////////////////////////////////////////////////////////////// + // length + ////////////////////////////////////////////////////////////////////////// + template <> + struct length_impl<basic_tuple_tag> { + template <typename ...Xn> + static constexpr auto apply(basic_tuple<Xn...> const&) { + return hana::size_c<sizeof...(Xn)>; + } + }; +#endif +BOOST_HANA_NAMESPACE_END + +#endif // !BOOST_HANA_BASIC_TUPLE_HPP |