1 | // Copyright David Abrahams 2003. Use, modification and distribution is |
2 | // subject to the Boost Software License, Version 1.0. (See accompanying |
3 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
4 | #ifndef BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ |
5 | # define BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ |
6 | |
7 | # include <boost/static_assert.hpp> |
8 | # include <boost/type_traits/is_convertible.hpp> |
9 | # include <boost/type_traits/is_same.hpp> |
10 | |
11 | # include <boost/mpl/placeholders.hpp> |
12 | # include <boost/mpl/aux_/lambda_support.hpp> |
13 | |
14 | namespace boost { |
15 | namespace iterators { |
16 | namespace detail { |
17 | |
18 | template <bool GreaterEqual, bool LessEqual> |
19 | struct minimum_category_impl; |
20 | |
21 | template <class T1, class T2> |
22 | struct error_not_related_by_convertibility; |
23 | |
24 | template <> |
25 | struct minimum_category_impl<true,false> |
26 | { |
27 | template <class T1, class T2> struct apply |
28 | { |
29 | typedef T2 type; |
30 | }; |
31 | }; |
32 | |
33 | template <> |
34 | struct minimum_category_impl<false,true> |
35 | { |
36 | template <class T1, class T2> struct apply |
37 | { |
38 | typedef T1 type; |
39 | }; |
40 | }; |
41 | |
42 | template <> |
43 | struct minimum_category_impl<true,true> |
44 | { |
45 | template <class T1, class T2> struct apply |
46 | { |
47 | BOOST_STATIC_ASSERT((is_same<T1,T2>::value)); |
48 | typedef T1 type; |
49 | }; |
50 | }; |
51 | |
52 | template <> |
53 | struct minimum_category_impl<false,false> |
54 | { |
55 | template <class T1, class T2> struct apply |
56 | : error_not_related_by_convertibility<T1,T2> |
57 | { |
58 | }; |
59 | }; |
60 | |
61 | } // namespace detail |
62 | |
63 | // |
64 | // Returns the minimum category type or fails to compile |
65 | // if T1 and T2 are unrelated. |
66 | // |
67 | template <class T1 = mpl::_1, class T2 = mpl::_2> |
68 | struct minimum_category |
69 | { |
70 | typedef boost::iterators::detail::minimum_category_impl< |
71 | ::boost::is_convertible<T1,T2>::value |
72 | , ::boost::is_convertible<T2,T1>::value |
73 | > outer; |
74 | |
75 | typedef typename outer::template apply<T1,T2> inner; |
76 | typedef typename inner::type type; |
77 | |
78 | BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) |
79 | }; |
80 | |
81 | template <> |
82 | struct minimum_category<mpl::_1,mpl::_2> |
83 | { |
84 | template <class T1, class T2> |
85 | struct apply : minimum_category<T1,T2> |
86 | {}; |
87 | |
88 | BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2,minimum_category,(mpl::_1,mpl::_2)) |
89 | }; |
90 | |
91 | } // namespace iterators |
92 | |
93 | } // namespace boost |
94 | |
95 | #endif // BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ |
96 | |