diff --git a/sprout/compressed_pair.hpp b/sprout/compressed_pair.hpp new file mode 100644 index 00000000..c7e78a6e --- /dev/null +++ b/sprout/compressed_pair.hpp @@ -0,0 +1,430 @@ +#ifndef SPROUT_COMPRESSED_PAIR_HPP +#define SPROUT_COMPRESSED_PAIR_HPP + +#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) + {} + first_reference first() { + return first_; + } + SPROUT_CONSTEXPR first_const_reference first() const { + return first_; + } + second_reference second() { + return second_; + } + SPROUT_CONSTEXPR second_const_reference second() const { + return second_; + } + void swap(compressed_pair_impl& other) { + using std::swap; + swap(first_, other.first_); + 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) + {} + first_reference first() { + return *this; + } + SPROUT_CONSTEXPR first_const_reference first() const { + return *this; + } + second_reference second() { + return second_; + } + SPROUT_CONSTEXPR second_const_reference second() const { + return second_; + } + void swap(compressed_pair_impl& other) { + using std::swap; + 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) + {} + first_reference first() { + return first_; + } + SPROUT_CONSTEXPR first_const_reference first() const { + return first_; + } + second_reference second() { + return *this; + } + SPROUT_CONSTEXPR second_const_reference second() const { + return *this; + } + void swap(compressed_pair_impl& other) { + using std::swap; + 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) + {} + first_reference first() { + return *this; + } + SPROUT_CONSTEXPR first_const_reference first() const { + return *this; + } + second_reference second() { + return *this; + } + SPROUT_CONSTEXPR second_const_reference second() const { + return *this; + } + void swap(compressed_pair_impl& other) {} + }; + 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) + {} + first_reference first() { + return *this; + } + SPROUT_CONSTEXPR first_const_reference first() const { + return *this; + } + second_reference second() { + return second_; + } + SPROUT_CONSTEXPR second_const_reference second() const { + return second_; + } + void swap(compressed_pair_impl& other) {} + }; + 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) + {} + first_reference first() { + return first_; + } + SPROUT_CONSTEXPR first_const_reference first() const { + return first_; + } + second_reference second() { + return second_; + } + SPROUT_CONSTEXPR second_const_reference second() const { + return second_; + } + void swap(compressed_pair_impl& other) { + using std::swap; + swap(first_, other.first_); + 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) + {} + SPROUT_CONSTEXPR explicit compressed_pair(first_param_type x) + : base_type(x) + {} + SPROUT_CONSTEXPR explicit compressed_pair(second_param_type y) + : base_type(y) + {} + first_reference first() { + return base_type::first(); + } + SPROUT_CONSTEXPR first_const_reference first() const { + return base_type::first(); + } + second_reference second() { + return base_type::second(); + } + SPROUT_CONSTEXPR second_const_reference second() const { + return base_type::second(); + } + 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) + {} + SPROUT_CONSTEXPR explicit compressed_pair(first_param_type x) + : base_type(x) + {} + first_reference first() { + return base_type::first(); + } + SPROUT_CONSTEXPR first_const_reference first() const { + return base_type::first(); + } + second_reference second() { + return base_type::second(); + } + SPROUT_CONSTEXPR second_const_reference second() const { + return base_type::second(); + } + void swap(compressed_pair& other) { + base_type::swap(other); + } + }; + template + inline void swap(sprout::compressed_pair& lhs, sprout::compressed_pair& rhs) { + lhs.swap(rhs); + } +} // namespace sprout + +#endif // #ifndef SPROUT_COMPRESSED_PAIR_HPP diff --git a/sprout/detail/call_traits.hpp b/sprout/detail/call_traits.hpp new file mode 100644 index 00000000..690e4a98 --- /dev/null +++ b/sprout/detail/call_traits.hpp @@ -0,0 +1,58 @@ +#ifndef SPROUT_DETAIL_CALL_TRAITS_HPP +#define SPROUT_DETAIL_CALL_TRAITS_HPP + +#include +#include + +namespace sprout { + namespace detail { + template + struct ct_impl_1 { + public: + typedef T const& param_type; + }; + template + struct ct_impl_1 { + public: + typedef T const param_type; + }; + + template + struct ct_impl { + public: + typedef T const& param_type; + }; + template + struct ct_impl { + public: + typedef typename sprout::detail::ct_impl_1::param_type param_type; + }; + template + struct ct_impl { + public: + typedef T const param_type; + }; + + template + struct call_traits { + public: + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef typename sprout::detail::ct_impl< + T, + std::is_pointer::value, + std::is_arithmetic::value + >::param_type param_type; + }; + template + struct call_traits { + typedef T& value_type; + typedef T& reference; + typedef T const& const_reference; + typedef T& param_type; + }; + } // namespace detail +} // namespace sprout + +#endif // #ifndef SPROUT_DETAIL_CALL_TRAITS_HPP