1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2014-2015, Oracle and/or its affiliates.
4 
5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
6 
7 // Licensed under the Boost Software License version 1.0.
8 // http://www.boost.org/users/license.html
9 
10 #ifndef BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP
11 #define BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP
12 
13 #include <boost/mpl/always.hpp>
14 #include <boost/mpl/bool.hpp>
15 #include <boost/mpl/vector.hpp>
16 
17 #include <boost/variant/variant_fwd.hpp>
18 
19 #include <boost/geometry/core/point_type.hpp>
20 
21 #include <boost/geometry/strategies/default_strategy.hpp>
22 #include <boost/geometry/strategies/distance.hpp>
23 
24 #include <boost/geometry/util/compress_variant.hpp>
25 #include <boost/geometry/util/transform_variant.hpp>
26 #include <boost/geometry/util/combine_if.hpp>
27 
28 #include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
29 
30 
31 namespace boost { namespace geometry
32 {
33 
34 namespace resolve_strategy
35 {
36 
37 template <typename Geometry1, typename Geometry2, typename Strategy>
38 struct comparable_distance_result
39     : strategy::distance::services::return_type
40         <
41             typename strategy::distance::services::comparable_type
42                 <
43                     Strategy
44                 >::type,
45             typename point_type<Geometry1>::type,
46             typename point_type<Geometry2>::type
47         >
48 {};
49 
50 template <typename Geometry1, typename Geometry2>
51 struct comparable_distance_result<Geometry1, Geometry2, default_strategy>
52     : comparable_distance_result
53         <
54             Geometry1,
55             Geometry2,
56             typename detail::distance::default_strategy
57                 <
58                     Geometry1, Geometry2
59                 >::type
60         >
61 {};
62 
63 } // namespace resolve_strategy
64 
65 
66 namespace resolve_variant
67 {
68 
69 template <typename Geometry1, typename Geometry2, typename Strategy>
70 struct comparable_distance_result
71     : resolve_strategy::comparable_distance_result
72         <
73             Geometry1,
74             Geometry2,
75             Strategy
76         >
77 {};
78 
79 
80 template
81 <
82     typename Geometry1,
83     BOOST_VARIANT_ENUM_PARAMS(typename T),
84     typename Strategy
85 >
86 struct comparable_distance_result
87     <
88         Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy
89     >
90 {
91     // A set of all variant type combinations that are compatible and
92     // implemented
93     typedef typename util::combine_if<
94         typename boost::mpl::vector1<Geometry1>,
95         typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
96         boost::mpl::always<boost::mpl::true_>
97     >::type possible_input_types;
98 
99     // The (possibly variant) result type resulting from these combinations
100     typedef typename compress_variant<
101         typename transform_variant<
102             possible_input_types,
103             resolve_strategy::comparable_distance_result<
104                 boost::mpl::first<boost::mpl::_>,
105                 boost::mpl::second<boost::mpl::_>,
106                 Strategy
107             >,
108             boost::mpl::back_inserter<boost::mpl::vector0<> >
109         >::type
110     >::type type;
111 };
112 
113 
114 // Distance arguments are commutative
115 template
116 <
117     BOOST_VARIANT_ENUM_PARAMS(typename T),
118     typename Geometry2,
119     typename Strategy
120 >
121 struct comparable_distance_result
122     <
123         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
124         Geometry2,
125         Strategy
126     > : public comparable_distance_result
127         <
128             Geometry2, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy
129         >
130 {};
131 
132 
133 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Strategy>
134 struct comparable_distance_result
135     <
136         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
137         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
138         Strategy
139     >
140 {
141     // A set of all variant type combinations that are compatible and
142     // implemented
143     typedef typename util::combine_if
144         <
145             typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
146             typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
147             boost::mpl::always<boost::mpl::true_>
148         >::type possible_input_types;
149 
150     // The (possibly variant) result type resulting from these combinations
151     typedef typename compress_variant<
152         typename transform_variant<
153             possible_input_types,
154             resolve_strategy::comparable_distance_result<
155                 boost::mpl::first<boost::mpl::_>,
156                 boost::mpl::second<boost::mpl::_>,
157                 Strategy
158             >,
159             boost::mpl::back_inserter<boost::mpl::vector0<> >
160         >::type
161     >::type type;
162 };
163 
164 } // namespace resolve_variant
165 
166 
167 
168 
169 
170 /*!
171 \brief Meta-function defining return type of comparable_distance function
172 \ingroup distance
173 */
174 template
175 <
176     typename Geometry1,
177     typename Geometry2 = Geometry1,
178     typename Strategy = void
179 >
180 struct comparable_distance_result
181     : resolve_variant::comparable_distance_result
182         <
183             Geometry1, Geometry2, Strategy
184         >
185 {};
186 
187 template <typename Geometry1, typename Geometry2>
188 struct comparable_distance_result<Geometry1, Geometry2, void>
189     : comparable_distance_result<Geometry1, Geometry2, default_strategy>
190 {};
191 
192 
193 }} // namespace boost::geometry
194 
195 
196 #endif // BOOST_GEOMETRY_STRATEGIES_COMPARABLE_DISTANCE_RESULT_HPP
197