summaryrefslogtreecommitdiff
path: root/boost/hana/basic_tuple.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/hana/basic_tuple.hpp')
-rw-r--r--boost/hana/basic_tuple.hpp299
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