/*============================================================================= Copyright (c) 2011-2013 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout 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 SPROUT_COMPRESSED_PAIR_HPP #define SPROUT_COMPRESSED_PAIR_HPP #include #include #include #include namespace sprout { namespace detail { template struct compressed_pair_switch; template struct compressed_pair_switch : public std::integral_constant {}; template struct compressed_pair_switch : public std::integral_constant {}; template struct compressed_pair_switch : public std::integral_constant {}; template struct compressed_pair_switch : public std::integral_constant {}; template struct compressed_pair_switch : public std::integral_constant {}; template struct compressed_pair_switch : public std::integral_constant {}; template class compressed_pair_impl; template class compressed_pair_impl { public: typedef T1 first_type; typedef T2 second_type; typedef typename sprout::detail::call_traits::param_type first_param_type; typedef typename sprout::detail::call_traits::param_type second_param_type; typedef typename sprout::detail::call_traits::reference first_reference; typedef typename sprout::detail::call_traits::reference second_reference; typedef typename sprout::detail::call_traits::const_reference first_const_reference; typedef typename sprout::detail::call_traits::const_reference second_const_reference; private: first_type first_; second_type second_; public: SPROUT_CONSTEXPR compressed_pair_impl() {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x, second_param_type y) : first_(x) , second_(y) {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x) : first_(x) {} SPROUT_CONSTEXPR compressed_pair_impl(second_param_type y) : second_(y) {} SPROUT_CXX14_CONSTEXPR first_reference first() { return first_; } SPROUT_CONSTEXPR first_const_reference first() const { return first_; } SPROUT_CXX14_CONSTEXPR second_reference second() { return second_; } SPROUT_CONSTEXPR second_const_reference second() const { return second_; } SPROUT_CXX14_CONSTEXPR void swap(compressed_pair_impl& other) SPROUT_NOEXCEPT_EXPR( SPROUT_NOEXCEPT_EXPR(sprout::swap(first_, other.first_)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(second_, other.second_)) ) { sprout::swap(first_, other.first_); sprout::swap(second_, other.second_); } }; template class compressed_pair_impl : protected std::remove_cv::type { public: typedef T1 first_type; typedef T2 second_type; typedef typename sprout::detail::call_traits::param_type first_param_type; typedef typename sprout::detail::call_traits::param_type second_param_type; typedef typename sprout::detail::call_traits::reference first_reference; typedef typename sprout::detail::call_traits::reference second_reference; typedef typename sprout::detail::call_traits::const_reference first_const_reference; typedef typename sprout::detail::call_traits::const_reference second_const_reference; private: second_type second_; public: SPROUT_CONSTEXPR compressed_pair_impl() {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x, second_param_type y) : first_type(x) , second_(y) {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x) : first_type(x) {} SPROUT_CONSTEXPR compressed_pair_impl(second_param_type y) : second_(y) {} SPROUT_CXX14_CONSTEXPR first_reference first() { return *this; } SPROUT_CONSTEXPR first_const_reference first() const { return *this; } SPROUT_CXX14_CONSTEXPR second_reference second() { return second_; } SPROUT_CONSTEXPR second_const_reference second() const { return second_; } SPROUT_CXX14_CONSTEXPR void swap(compressed_pair_impl& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(sprout::swap(second_, other.second_))) { sprout::swap(second_, other.second_); } }; template class compressed_pair_impl : protected std::remove_cv::type { public: typedef T1 first_type; typedef T2 second_type; typedef typename sprout::detail::call_traits::param_type first_param_type; typedef typename sprout::detail::call_traits::param_type second_param_type; typedef typename sprout::detail::call_traits::reference first_reference; typedef typename sprout::detail::call_traits::reference second_reference; typedef typename sprout::detail::call_traits::const_reference first_const_reference; typedef typename sprout::detail::call_traits::const_reference second_const_reference; private: first_type first_; public: SPROUT_CONSTEXPR compressed_pair_impl() {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x, second_param_type y) : first_(x) , second_type(y) {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x) : first_(x) {} SPROUT_CONSTEXPR compressed_pair_impl(second_param_type y) : second_type(y) {} SPROUT_CXX14_CONSTEXPR first_reference first() { return first_; } SPROUT_CONSTEXPR first_const_reference first() const { return first_; } SPROUT_CXX14_CONSTEXPR second_reference second() { return *this; } SPROUT_CONSTEXPR second_const_reference second() const { return *this; } SPROUT_CXX14_CONSTEXPR void swap(compressed_pair_impl& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(sprout::swap(first_, other.first_))) { sprout::swap(first_, other.first_); } }; template class compressed_pair_impl : protected std::remove_cv::type , protected std::remove_cv::type { public: typedef T1 first_type; typedef T2 second_type; typedef typename sprout::detail::call_traits::param_type first_param_type; typedef typename sprout::detail::call_traits::param_type second_param_type; typedef typename sprout::detail::call_traits::reference first_reference; typedef typename sprout::detail::call_traits::reference second_reference; typedef typename sprout::detail::call_traits::const_reference first_const_reference; typedef typename sprout::detail::call_traits::const_reference second_const_reference; public: SPROUT_CONSTEXPR compressed_pair_impl() {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x, second_param_type y) : first_type(x) , second_type(y) {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x) : first_type(x) {} SPROUT_CONSTEXPR compressed_pair_impl(second_param_type y) : second_type(y) {} SPROUT_CXX14_CONSTEXPR first_reference first() { return *this; } SPROUT_CONSTEXPR first_const_reference first() const { return *this; } SPROUT_CXX14_CONSTEXPR second_reference second() { return *this; } SPROUT_CONSTEXPR second_const_reference second() const { return *this; } SPROUT_CXX14_CONSTEXPR void swap(compressed_pair_impl&) {} }; template class compressed_pair_impl : protected std::remove_cv::type { public: typedef T1 first_type; typedef T2 second_type; typedef typename sprout::detail::call_traits::param_type first_param_type; typedef typename sprout::detail::call_traits::param_type second_param_type; typedef typename sprout::detail::call_traits::reference first_reference; typedef typename sprout::detail::call_traits::reference second_reference; typedef typename sprout::detail::call_traits::const_reference first_const_reference; typedef typename sprout::detail::call_traits::const_reference second_const_reference; private: second_type second_; public: SPROUT_CONSTEXPR compressed_pair_impl() {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x, second_param_type y) : first_type(x) , second_(y) {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x) : first_type(x) , second_(x) {} SPROUT_CXX14_CONSTEXPR first_reference first() { return *this; } SPROUT_CONSTEXPR first_const_reference first() const { return *this; } SPROUT_CXX14_CONSTEXPR second_reference second() { return second_; } SPROUT_CONSTEXPR second_const_reference second() const { return second_; } SPROUT_CXX14_CONSTEXPR void swap(compressed_pair_impl&) {} }; template class compressed_pair_impl { public: typedef T1 first_type; typedef T2 second_type; typedef typename sprout::detail::call_traits::param_type first_param_type; typedef typename sprout::detail::call_traits::param_type second_param_type; typedef typename sprout::detail::call_traits::reference first_reference; typedef typename sprout::detail::call_traits::reference second_reference; typedef typename sprout::detail::call_traits::const_reference first_const_reference; typedef typename sprout::detail::call_traits::const_reference second_const_reference; private: first_type first_; second_type second_; public: SPROUT_CONSTEXPR compressed_pair_impl() {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x, second_param_type y) : first_(x) , second_(y) {} SPROUT_CONSTEXPR compressed_pair_impl(first_param_type x) : first_(x) , second_(x) {} SPROUT_CXX14_CONSTEXPR first_reference first() { return first_; } SPROUT_CONSTEXPR first_const_reference first() const { return first_; } SPROUT_CXX14_CONSTEXPR second_reference second() { return second_; } SPROUT_CONSTEXPR second_const_reference second() const { return second_; } SPROUT_CXX14_CONSTEXPR void swap(compressed_pair_impl& other) SPROUT_NOEXCEPT_EXPR( SPROUT_NOEXCEPT_EXPR(sprout::swap(first_, other.first_)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(second_, other.second_)) ) { sprout::swap(first_, other.first_); sprout::swap(second_, other.second_); } }; } // namespace detail // // compressed_pair // template class compressed_pair : private sprout::detail::compressed_pair_impl< T1, T2, sprout::detail::compressed_pair_switch< T1, T2, std::is_same::type, typename std::remove_cv::type>::value, std::is_empty::value, std::is_empty::value >::value > { private: typedef sprout::detail::compressed_pair_impl< T1, T2, sprout::detail::compressed_pair_switch< T1, T2, std::is_same::type, typename std::remove_cv::type>::value, std::is_empty::value, std::is_empty::value >::value > base_type; public: typedef T1 first_type; typedef T2 second_type; typedef typename sprout::detail::call_traits::param_type first_param_type; typedef typename sprout::detail::call_traits::param_type second_param_type; typedef typename sprout::detail::call_traits::reference first_reference; typedef typename sprout::detail::call_traits::reference second_reference; typedef typename sprout::detail::call_traits::const_reference first_const_reference; typedef typename sprout::detail::call_traits::const_reference second_const_reference; public: SPROUT_CONSTEXPR compressed_pair() : base_type() {} SPROUT_CONSTEXPR compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {} explicit SPROUT_CONSTEXPR compressed_pair(first_param_type x) : base_type(x) {} explicit SPROUT_CONSTEXPR compressed_pair(second_param_type y) : base_type(y) {} SPROUT_CXX14_CONSTEXPR first_reference first() { return base_type::first(); } SPROUT_CONSTEXPR first_const_reference first() const { return base_type::first(); } SPROUT_CXX14_CONSTEXPR second_reference second() { return base_type::second(); } SPROUT_CONSTEXPR second_const_reference second() const { return base_type::second(); } SPROUT_CXX14_CONSTEXPR void swap(compressed_pair& other) { base_type::swap(other); } }; template class compressed_pair : private sprout::detail::compressed_pair_impl< T, T, sprout::detail::compressed_pair_switch< T, T, std::is_same::type, typename std::remove_cv::type>::value, std::is_empty::value, std::is_empty::value >::value > { private: typedef sprout::detail::compressed_pair_impl< T, T, sprout::detail::compressed_pair_switch< T, T, std::is_same::type, typename std::remove_cv::type>::value, std::is_empty::value, std::is_empty::value >::value > base_type; public: typedef T first_type; typedef T second_type; typedef typename sprout::detail::call_traits::param_type first_param_type; typedef typename sprout::detail::call_traits::param_type second_param_type; typedef typename sprout::detail::call_traits::reference first_reference; typedef typename sprout::detail::call_traits::reference second_reference; typedef typename sprout::detail::call_traits::const_reference first_const_reference; typedef typename sprout::detail::call_traits::const_reference second_const_reference; public: SPROUT_CONSTEXPR compressed_pair() : base_type() {} SPROUT_CONSTEXPR compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {} explicit SPROUT_CONSTEXPR compressed_pair(first_param_type x) : base_type(x) {} SPROUT_CXX14_CONSTEXPR first_reference first() { return base_type::first(); } SPROUT_CONSTEXPR first_const_reference first() const { return base_type::first(); } SPROUT_CXX14_CONSTEXPR second_reference second() { return base_type::second(); } SPROUT_CONSTEXPR second_const_reference second() const { return base_type::second(); } SPROUT_CXX14_CONSTEXPR void swap(compressed_pair& other) { base_type::swap(other); } }; // // swap // template inline SPROUT_CXX14_CONSTEXPR void swap(sprout::compressed_pair& lhs, sprout::compressed_pair& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { lhs.swap(rhs); } } // namespace sprout #endif // #ifndef SPROUT_COMPRESSED_PAIR_HPP