/*-----------------------------------------------------------------------------+ Copyright (c) 2009-2009: Joachim Faulhaber +------------------------------------------------------------------------------+ Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENCE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +-----------------------------------------------------------------------------*/ #ifndef BOOST_ICL_DETAIL_MAPPED_REFERENCE_HPP_JOFA_091108 #define BOOST_ICL_DETAIL_MAPPED_REFERENCE_HPP_JOFA_091108 #include <boost/type_traits/is_const.hpp> #include <boost/type_traits/remove_const.hpp> #include <boost/mpl/if.hpp> #include <boost/icl/type_traits/is_concept_equivalent.hpp> namespace boost{namespace icl { template<class FirstT, class SecondT> class mapped_reference; //------------------------------------------------------------------------------ template<class Type> struct is_mapped_reference_combinable{ typedef is_mapped_reference_combinable type; BOOST_STATIC_CONSTANT(bool, value = false); }; template<class FirstT, class SecondT> struct is_mapped_reference_combinable<std::pair<const FirstT,SecondT> > { typedef is_mapped_reference_combinable<std::pair<const FirstT,SecondT> > type; BOOST_STATIC_CONSTANT(bool, value = true); }; template<class FirstT, class SecondT> struct is_mapped_reference_combinable<std::pair<FirstT,SecondT> > { typedef is_mapped_reference_combinable<std::pair<FirstT,SecondT> > type; BOOST_STATIC_CONSTANT(bool, value = true); }; //------------------------------------------------------------------------------ template<class Type> struct is_mapped_reference_or_combinable{ typedef is_mapped_reference_or_combinable type; BOOST_STATIC_CONSTANT(bool, value = is_mapped_reference_combinable<Type>::value); }; template<class FirstT, class SecondT> struct is_mapped_reference_or_combinable<mapped_reference<FirstT,SecondT> > { typedef is_mapped_reference_or_combinable<mapped_reference<FirstT,SecondT> > type; BOOST_STATIC_CONSTANT(bool, value = true); }; //------------------------------------------------------------------------------ template<class FirstT, class SecondT> class mapped_reference { private: mapped_reference& operator = (const mapped_reference&); public: typedef FirstT first_type; typedef SecondT second_type; typedef mapped_reference type; typedef typename mpl::if_<is_const<second_type>, second_type&, const second_type&>::type second_reference_type; typedef std::pair< first_type, second_type> std_pair_type; typedef std::pair<const first_type, second_type> key_std_pair_type; const first_type& first ; second_reference_type second; mapped_reference(const FirstT& fst, second_reference_type snd) : first(fst), second(snd){} template<class FstT, class SndT> mapped_reference(const mapped_reference<FstT, SndT>& source): first(source.first), second(source.second){} template<class FstT, class SndT> operator std::pair<FstT,SndT>(){ return std::pair<FstT,SndT>(first, second); } template<class Comparand> typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type operator == (const Comparand& right)const { return first == right.first && second == right.second; } template<class Comparand> typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type operator != (const Comparand& right)const { return !(*this == right); } template<class Comparand> typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type operator < (const Comparand& right)const { return first < right.first ||(!(right.first < first) && second < right.second); } template<class Comparand> typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type operator > (const Comparand& right)const { return first > right.first ||(!(right.first > first) && second > right.second); } template<class Comparand> typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type operator <= (const Comparand& right)const { return !(*this > right); } template<class Comparand> typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type operator >= (const Comparand& right)const { return !(*this < right); } }; //------------------------------------------------------------------------------ template<class FirstT, class SecondT, class StdPairT> inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type operator == ( const StdPairT& left, const mapped_reference<FirstT, SecondT>& right) { return right == left; } template<class FirstT, class SecondT, class StdPairT> inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type operator != ( const StdPairT& left, const mapped_reference<FirstT, SecondT>& right) { return !(right == left); } //------------------------------------------------------------------------------ template<class FirstT, class SecondT, class StdPairT> inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type operator < ( const StdPairT& left, const mapped_reference<FirstT, SecondT>& right) { return right > left; } //------------------------------------------------------------------------------ template<class FirstT, class SecondT, class StdPairT> inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type operator > ( const StdPairT& left, const mapped_reference<FirstT, SecondT>& right) { return right < left; } //------------------------------------------------------------------------------ template<class FirstT, class SecondT, class StdPairT> inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type operator <= ( const StdPairT& left, const mapped_reference<FirstT, SecondT>& right) { return !(right < left); } //------------------------------------------------------------------------------ template<class FirstT, class SecondT, class StdPairT> inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type operator >= ( const StdPairT& left, const mapped_reference<FirstT, SecondT>& right) { return !(left < right); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ template<class FirstT, class SecondT> inline mapped_reference<FirstT, SecondT> make_mapped_reference(const FirstT& left, SecondT& right) { return mapped_reference<FirstT, SecondT>(left, right); } }} // namespace icl boost #endif // BOOST_ICL_DETAIL_MAPPED_REFERENCE_HPP_JOFA_091108