1 /*-----------------------------------------------------------------------------+
2 Copyright (c) 2009-2009: Joachim Faulhaber
3 +------------------------------------------------------------------------------+
4    Distributed under the Boost Software License, Version 1.0.
5       (See accompanying file LICENCE.txt or copy at
6            http://www.boost.org/LICENSE_1_0.txt)
7 +-----------------------------------------------------------------------------*/
8 #ifndef BOOST_ICL_DETAIL_MAPPED_REFERENCE_HPP_JOFA_091108
9 #define BOOST_ICL_DETAIL_MAPPED_REFERENCE_HPP_JOFA_091108
10 
11 #include <boost/type_traits/is_const.hpp>
12 #include <boost/type_traits/remove_const.hpp>
13 #include <boost/mpl/if.hpp>
14 #include <boost/icl/type_traits/is_concept_equivalent.hpp>
15 
16 namespace boost{namespace icl
17 {
18 
19 template<class FirstT, class SecondT> class mapped_reference;
20 
21 //------------------------------------------------------------------------------
22 template<class Type>
23 struct is_mapped_reference_combinable{
24     typedef is_mapped_reference_combinable type;
25     BOOST_STATIC_CONSTANT(bool, value = false);
26 };
27 
28 template<class FirstT, class SecondT>
29 struct is_mapped_reference_combinable<std::pair<const FirstT,SecondT> >
30 {
31     typedef is_mapped_reference_combinable<std::pair<const FirstT,SecondT> > type;
32     BOOST_STATIC_CONSTANT(bool, value = true);
33 };
34 
35 template<class FirstT, class SecondT>
36 struct is_mapped_reference_combinable<std::pair<FirstT,SecondT> >
37 {
38     typedef is_mapped_reference_combinable<std::pair<FirstT,SecondT> > type;
39     BOOST_STATIC_CONSTANT(bool, value = true);
40 };
41 
42 //------------------------------------------------------------------------------
43 template<class Type>
44 struct is_mapped_reference_or_combinable{
45     typedef is_mapped_reference_or_combinable type;
46     BOOST_STATIC_CONSTANT(bool, value = is_mapped_reference_combinable<Type>::value);
47 };
48 
49 template<class FirstT, class SecondT>
50 struct is_mapped_reference_or_combinable<mapped_reference<FirstT,SecondT> >
51 {
52     typedef is_mapped_reference_or_combinable<mapped_reference<FirstT,SecondT> > type;
53     BOOST_STATIC_CONSTANT(bool, value = true);
54 };
55 
56 
57 
58 //------------------------------------------------------------------------------
59 template<class FirstT, class SecondT>
60 class mapped_reference
61 {
62 private:
63     mapped_reference& operator = (const mapped_reference&);
64 public:
65     typedef FirstT  first_type;
66     typedef SecondT second_type;
67     typedef mapped_reference type;
68 
69     typedef typename
70         mpl::if_<is_const<second_type>,
71                        second_type&,
72                  const second_type&>::type second_reference_type;
73 
74     typedef std::pair<      first_type, second_type>     std_pair_type;
75     typedef std::pair<const first_type, second_type> key_std_pair_type;
76 
77     const first_type&     first ;
78     second_reference_type second;
79 
mapped_reference(const FirstT & fst,second_reference_type snd)80     mapped_reference(const FirstT& fst, second_reference_type snd) : first(fst), second(snd){}
81 
82     template<class FstT, class SndT>
mapped_reference(const mapped_reference<FstT,SndT> & source)83     mapped_reference(const mapped_reference<FstT, SndT>& source):
84         first(source.first), second(source.second){}
85 
86     template<class FstT, class SndT>
operator std::pair<FstT,SndT>()87     operator std::pair<FstT,SndT>(){ return std::pair<FstT,SndT>(first, second); }
88 
89     template<class Comparand>
90     typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type
operator ==(const Comparand & right) const91     operator == (const Comparand& right)const
92     { return first == right.first && second == right.second; }
93 
94     template<class Comparand>
95     typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type
operator !=(const Comparand & right) const96     operator != (const Comparand& right)const
97     { return !(*this == right); }
98 
99     template<class Comparand>
100     typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type
operator <(const Comparand & right) const101     operator < (const Comparand& right)const
102     {
103         return         first < right.first
104             ||(!(right.first <       first) && second < right.second);
105     }
106 
107     template<class Comparand>
108     typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type
operator >(const Comparand & right) const109     operator > (const Comparand& right)const
110     {
111         return         first > right.first
112             ||(!(right.first >       first) && second > right.second);
113     }
114 
115     template<class Comparand>
116     typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type
operator <=(const Comparand & right) const117     operator <= (const Comparand& right)const
118     {
119         return !(*this > right);
120     }
121 
122     template<class Comparand>
123     typename enable_if<is_mapped_reference_or_combinable<Comparand>, bool>::type
operator >=(const Comparand & right) const124     operator >= (const Comparand& right)const
125     {
126         return !(*this < right);
127     }
128 
129 };
130 
131 //------------------------------------------------------------------------------
132 template<class FirstT, class SecondT, class StdPairT>
133 inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type
operator ==(const StdPairT & left,const mapped_reference<FirstT,SecondT> & right)134 operator == (                         const StdPairT& left,
135              const mapped_reference<FirstT, SecondT>& right)
136 {
137     return right == left;
138 }
139 
140 template<class FirstT, class SecondT, class StdPairT>
141 inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type
operator !=(const StdPairT & left,const mapped_reference<FirstT,SecondT> & right)142 operator != (                         const StdPairT& left,
143              const mapped_reference<FirstT, SecondT>& right)
144 {
145     return !(right == left);
146 }
147 
148 //------------------------------------------------------------------------------
149 template<class FirstT, class SecondT, class StdPairT>
150 inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type
operator <(const StdPairT & left,const mapped_reference<FirstT,SecondT> & right)151 operator < (                         const StdPairT& left,
152             const mapped_reference<FirstT, SecondT>& right)
153 {
154     return right > left;
155 }
156 
157 //------------------------------------------------------------------------------
158 template<class FirstT, class SecondT, class StdPairT>
159 inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type
operator >(const StdPairT & left,const mapped_reference<FirstT,SecondT> & right)160 operator > (                         const StdPairT& left,
161             const mapped_reference<FirstT, SecondT>& right)
162 {
163     return right < left;
164 }
165 
166 //------------------------------------------------------------------------------
167 template<class FirstT, class SecondT, class StdPairT>
168 inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type
operator <=(const StdPairT & left,const mapped_reference<FirstT,SecondT> & right)169 operator <= (                         const StdPairT& left,
170              const mapped_reference<FirstT, SecondT>& right)
171 {
172     return !(right < left);
173 }
174 
175 //------------------------------------------------------------------------------
176 template<class FirstT, class SecondT, class StdPairT>
177 inline typename enable_if<is_mapped_reference_combinable<StdPairT>, bool>::type
operator >=(const StdPairT & left,const mapped_reference<FirstT,SecondT> & right)178 operator >= (                         const StdPairT& left,
179              const mapped_reference<FirstT, SecondT>& right)
180 {
181     return !(left < right);
182 }
183 
184 //------------------------------------------------------------------------------
185 //------------------------------------------------------------------------------
186 template<class FirstT, class SecondT>
make_mapped_reference(const FirstT & left,SecondT & right)187 inline mapped_reference<FirstT, SecondT> make_mapped_reference(const FirstT& left, SecondT& right)
188 { return mapped_reference<FirstT, SecondT>(left, right); }
189 
190 }} // namespace icl boost
191 
192 #endif // BOOST_ICL_DETAIL_MAPPED_REFERENCE_HPP_JOFA_091108
193