summaryrefslogtreecommitdiff
path: root/boost/hana/tuple.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/hana/tuple.hpp')
-rw-r--r--boost/hana/tuple.hpp305
1 files changed, 305 insertions, 0 deletions
diff --git a/boost/hana/tuple.hpp b/boost/hana/tuple.hpp
new file mode 100644
index 0000000000..7273a6c2e0
--- /dev/null
+++ b/boost/hana/tuple.hpp
@@ -0,0 +1,305 @@
+/*!
+@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