diff options
Diffstat (limited to 'boost/hof/detail/compressed_pair.hpp')
-rw-r--r-- | boost/hof/detail/compressed_pair.hpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/boost/hof/detail/compressed_pair.hpp b/boost/hof/detail/compressed_pair.hpp new file mode 100644 index 0000000000..b7c320e2da --- /dev/null +++ b/boost/hof/detail/compressed_pair.hpp @@ -0,0 +1,130 @@ +/*============================================================================= + Copyright (c) 2015 Paul Fultz II + compressed_pair.h + 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 BOOST_HOF_GUARD_COMPRESSED_PAIR_H +#define BOOST_HOF_GUARD_COMPRESSED_PAIR_H + +#include <boost/hof/detail/delegate.hpp> +#include <boost/hof/detail/move.hpp> +#include <boost/hof/detail/forward.hpp> +#include <boost/hof/config.hpp> +#include <boost/hof/always.hpp> +#include <boost/hof/alias.hpp> + +#ifndef BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND +#define BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND !BOOST_HOF_HAS_EBO +#endif + +namespace boost { namespace hof { namespace detail { + +template<class First, class Second, class=void> +struct compressed_pair; + +template<int I, class T, class U> +struct pair_tag +{}; + +#if BOOST_HOF_COMPRESSED_PAIR_USE_EBO_WORKAROUND + +template<class T, class U> +struct is_same_template +: std::false_type +{}; + +template<template<class...> class X, class... Ts, class... Us> +struct is_same_template<X<Ts...>, X<Us...>> +: std::true_type +{}; + +#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7) + +template<class T, class U> +struct is_related_template +: std::false_type +{}; + +#else + +template<class T, class U> +struct is_related_template +: is_same_template<T, U> +{}; + +#endif + +template<class T, class U> +struct is_related +: std::integral_constant<bool, std::is_base_of<T, U>::value || std::is_base_of<U, T>::value || is_related_template<T, U>::value> +{}; + +template<int I, class T, class U> +struct pair_holder +: std::conditional<( + is_related<T, U>::value), + detail::alias_empty<T, pair_tag<I, T, U>>, + detail::alias_try_inherit<T, pair_tag<I, T, U>> +>::type +{}; +#else +template<int I, class T, class U> +struct pair_holder +: detail::alias_try_inherit<T, pair_tag<I, T, U>> +{}; +#endif + +// TODO: Empty optimizations for MSVC +template< + class First, + class Second +> +struct compressed_pair<First, Second> +: pair_holder<0, First, Second>::type, pair_holder<1, Second, First>::type +{ + typedef typename pair_holder<0, First, Second>::type first_base; + typedef typename pair_holder<1, Second, First>::type second_base; + template<class X, class Y, + BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(First, X&&), + BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(Second, Y&&) + > + constexpr compressed_pair(X&& x, Y&& y) + noexcept(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(first_base, X&&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(second_base, Y&&)) + : first_base(BOOST_HOF_FORWARD(X)(x)), second_base(BOOST_HOF_FORWARD(Y)(y)) + {} + + BOOST_HOF_INHERIT_DEFAULT(compressed_pair, first_base, second_base) + + template<class Base, class... Xs> + constexpr const Base& get_alias_base(Xs&&... xs) const noexcept + { + return boost::hof::always_ref(*this)(xs...); + } + + template<class... Xs> + constexpr const First& first(Xs&&... xs) const noexcept + { + return boost::hof::alias_value(this->get_alias_base<first_base>(xs...), xs...); + } + + template<class... Xs> + constexpr const Second& second(Xs&&... xs) const noexcept + { + return boost::hof::alias_value(this->get_alias_base<second_base>(xs...), xs...); + } + +}; + +template<class T, class U> +constexpr compressed_pair<T, U> make_compressed_pair(T x, U y) +noexcept(BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) && BOOST_HOF_IS_NOTHROW_MOVE_CONSTRUCTIBLE(U)) +{ + return {static_cast<T&&>(x), static_cast<U&&>(y)}; +} + + +}}} // namespace boost::hof + +#endif |