1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
7 // This file was modified by Oracle on 2014-2020.
8 // Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
12 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
14 // Use, modification and distribution is subject to the Boost Software License,
15 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
16 // http://www.boost.org/LICENSE_1_0.txt)
18 #ifndef BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
19 #define BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
22 #include <type_traits>
25 namespace boost { namespace geometry
28 #ifndef DOXYGEN_NO_DETAIL
30 namespace detail { namespace select_most_precise
37 // 3 - non-fundamental
42 std::is_void<T>::value,
43 std::integral_constant<int, 0>,
46 std::is_fundamental<T>::value,
49 std::is_floating_point<T>::value,
50 std::integral_constant<int, 2>,
51 std::integral_constant<int, 1>
53 std::integral_constant<int, 3>
61 : std::integral_constant<std::size_t, sizeof(T)>
65 struct type_size<void>
66 : std::integral_constant<std::size_t, 0>
70 }} // namespace detail::select_most_precise
71 #endif // DOXYGEN_NO_DETAIL
75 \brief Meta-function to select the most accurate type for
78 \details select_most_precise classes, compares types on compile time.
79 For example, if an addition must be done with a double and an integer, the
80 result must be a double.
81 If both types are integer, the result can be an integer.
82 \note It is different from the "promote" class, already in boost. That
83 class promotes e.g. a (one) float to a double. This class selects a
84 type from two types. It takes the most accurate, but does not promote
86 \note If the input is a non-fundamental type, it might be a calculation
87 type such as a GMP-value or another high precision value. Therefore,
88 if one is non-fundamental, that one is chosen.
89 \note If both types are non-fundamental, the result is indeterminate and
90 currently the first one is chosen.
92 template <typename ...Types>
93 struct select_most_precise
99 struct select_most_precise<T>
104 template <typename T1, typename T2>
105 struct select_most_precise<T1, T2>
107 static const int priority1 = detail::select_most_precise::type_priority<T1>::value;
108 static const int priority2 = detail::select_most_precise::type_priority<T2>::value;
109 static const std::size_t size1 = detail::select_most_precise::type_size<T1>::value;
110 static const std::size_t size2 = detail::select_most_precise::type_size<T2>::value;
112 typedef std::conditional_t
114 (priority1 > priority2),
118 (priority2 > priority1),
120 std::conditional_t // priority1 == priority2
122 (priority1 == 0 || priority1 == 3), // both void or non-fundamental
124 std::conditional_t // both fundamental
135 template <typename T1, typename T2, typename ...Types>
136 struct select_most_precise<T1, T2, Types...>
138 typedef typename select_most_precise
140 typename select_most_precise<T1, T2>::type,
141 typename select_most_precise<Types...>::type
146 }} // namespace boost::geometry
148 #endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP