Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:11

0001 // Copyright 2015-2019 Hans Dembinski
0002 //
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt
0005 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_HISTOGRAM_DETAIL_DETECT_HPP
0008 #define BOOST_HISTOGRAM_DETAIL_DETECT_HPP
0009 
0010 #include <boost/histogram/fwd.hpp>
0011 #include <boost/mp11/function.hpp> // mp_and, mp_or
0012 #include <boost/mp11/integral.hpp> // mp_not
0013 #include <boost/mp11/list.hpp>     // mp_first
0014 #include <iterator>
0015 #include <tuple>
0016 #include <type_traits>
0017 
0018 // forward declaration
0019 namespace boost {
0020 namespace variant2 {
0021 template <class...>
0022 class variant;
0023 } // namespace variant2
0024 } // namespace boost
0025 
0026 namespace boost {
0027 namespace histogram {
0028 namespace detail {
0029 
0030 template <class...>
0031 using void_t = void;
0032 
0033 struct detect_base {
0034   template <class T>
0035   static T&& val();
0036   template <class T>
0037   static T& ref();
0038   template <class T>
0039   static T const& cref();
0040 };
0041 
0042 #define BOOST_HISTOGRAM_DETAIL_DETECT(name, cond)       \
0043   template <class U>                                    \
0044   struct name##_impl : detect_base {                    \
0045     template <class T>                                  \
0046     static mp11::mp_true test(T& t, decltype(cond, 0)); \
0047     template <class T>                                  \
0048     static mp11::mp_false test(T&, float);              \
0049     using type = decltype(test<U>(ref<U>(), 0));        \
0050   };                                                    \
0051   template <class T>                                    \
0052   using name = typename name##_impl<T>::type
0053 
0054 #define BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(name, cond)      \
0055   template <class V, class W>                                 \
0056   struct name##_impl : detect_base {                          \
0057     template <class T, class U>                               \
0058     static mp11::mp_true test(T& t, U& u, decltype(cond, 0)); \
0059     template <class T, class U>                               \
0060     static mp11::mp_false test(T&, U&, float);                \
0061     using type = decltype(test<V, W>(ref<V>(), ref<W>(), 0)); \
0062   };                                                          \
0063   template <class T, class U = T>                             \
0064   using name = typename name##_impl<T, U>::type
0065 
0066 // reset has overloads, trying to get pmf in this case always fails
0067 BOOST_HISTOGRAM_DETAIL_DETECT(has_method_reset, t.reset(0));
0068 
0069 BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable, t[0]);
0070 
0071 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(is_transform, (t.inverse(t.forward(u))));
0072 
0073 BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable_container,
0074                               (t[0], t.size(), std::begin(t), std::end(t)));
0075 
0076 BOOST_HISTOGRAM_DETAIL_DETECT(is_vector_like,
0077                               (t[0], t.size(), t.resize(0), std::begin(t), std::end(t)));
0078 
0079 BOOST_HISTOGRAM_DETAIL_DETECT(is_array_like, (t[0], t.size(), std::tuple_size<T>::value,
0080                                               std::begin(t), std::end(t)));
0081 
0082 BOOST_HISTOGRAM_DETAIL_DETECT(is_map_like, ((typename T::key_type*)nullptr,
0083                                             (typename T::mapped_type*)nullptr,
0084                                             std::begin(t), std::end(t)));
0085 
0086 // ok: is_axis is false for axis::variant, because T::index is templated
0087 BOOST_HISTOGRAM_DETAIL_DETECT(is_axis, (t.size(), &T::index));
0088 
0089 BOOST_HISTOGRAM_DETAIL_DETECT(is_iterable, (std::begin(t), std::end(t)));
0090 
0091 BOOST_HISTOGRAM_DETAIL_DETECT(is_iterator,
0092                               (typename std::iterator_traits<T>::iterator_category{}));
0093 
0094 BOOST_HISTOGRAM_DETAIL_DETECT(is_streamable, (std::declval<std::ostream&>() << t));
0095 
0096 BOOST_HISTOGRAM_DETAIL_DETECT(is_allocator, (&T::allocate, &T::deallocate));
0097 
0098 BOOST_HISTOGRAM_DETAIL_DETECT(has_operator_preincrement, ++t);
0099 
0100 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_equal, (cref<T>() == u));
0101 
0102 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_radd, (t += u));
0103 
0104 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rsub, (t -= u));
0105 
0106 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rmul, (t *= u));
0107 
0108 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rdiv, (t /= u));
0109 
0110 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_method_eq, (cref<T>().operator==(u)));
0111 
0112 BOOST_HISTOGRAM_DETAIL_DETECT(has_threading_support, (T::has_threading_support));
0113 
0114 // stronger form of std::is_convertible that works with explicit operator T and ctors
0115 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(is_explicitly_convertible, static_cast<U>(t));
0116 
0117 BOOST_HISTOGRAM_DETAIL_DETECT(is_complete, sizeof(T));
0118 
0119 template <class T>
0120 using is_storage = mp11::mp_and<is_indexable_container<T>, has_method_reset<T>,
0121                                 has_threading_support<T>>;
0122 
0123 template <class T>
0124 using is_adaptible =
0125     mp11::mp_and<mp11::mp_not<is_storage<T>>,
0126                  mp11::mp_or<is_vector_like<T>, is_array_like<T>, is_map_like<T>>>;
0127 
0128 template <class T>
0129 struct is_tuple_impl : std::false_type {};
0130 
0131 template <class... Ts>
0132 struct is_tuple_impl<std::tuple<Ts...>> : std::true_type {};
0133 
0134 template <class T>
0135 using is_tuple = typename is_tuple_impl<T>::type;
0136 
0137 template <class T>
0138 struct is_variant_impl : std::false_type {};
0139 
0140 template <class... Ts>
0141 struct is_variant_impl<boost::variant2::variant<Ts...>> : std::true_type {};
0142 
0143 template <class T>
0144 using is_variant = typename is_variant_impl<T>::type;
0145 
0146 template <class T>
0147 struct is_axis_variant_impl : std::false_type {};
0148 
0149 template <class... Ts>
0150 struct is_axis_variant_impl<axis::variant<Ts...>> : std::true_type {};
0151 
0152 template <class T>
0153 using is_axis_variant = typename is_axis_variant_impl<T>::type;
0154 
0155 template <class T>
0156 using is_any_axis = mp11::mp_or<is_axis<T>, is_axis_variant<T>>;
0157 
0158 template <class T>
0159 using is_sequence_of_axis = mp11::mp_and<is_iterable<T>, is_axis<mp11::mp_first<T>>>;
0160 
0161 template <class T>
0162 using is_sequence_of_axis_variant =
0163     mp11::mp_and<is_iterable<T>, is_axis_variant<mp11::mp_first<T>>>;
0164 
0165 template <class T>
0166 using is_sequence_of_any_axis =
0167     mp11::mp_and<is_iterable<T>, is_any_axis<mp11::mp_first<T>>>;
0168 
0169 // Poor-mans concept checks.
0170 // These must be structs not aliases, so their names pop up in compiler errors.
0171 template <class T, class = std::enable_if_t<is_storage<std::decay_t<T>>::value>>
0172 struct requires_storage {};
0173 
0174 template <class T, class _ = std::decay_t<T>,
0175           class = std::enable_if_t<(is_storage<_>::value || is_adaptible<_>::value)>>
0176 struct requires_storage_or_adaptible {};
0177 
0178 template <class T, class = std::enable_if_t<is_iterator<std::decay_t<T>>::value>>
0179 struct requires_iterator {};
0180 
0181 template <class T, class = std::enable_if_t<
0182                        is_iterable<std::remove_cv_t<std::remove_reference_t<T>>>::value>>
0183 struct requires_iterable {};
0184 
0185 template <class T, class = std::enable_if_t<is_axis<std::decay_t<T>>::value>>
0186 struct requires_axis {};
0187 
0188 template <class T, class = std::enable_if_t<is_any_axis<std::decay_t<T>>::value>>
0189 struct requires_any_axis {};
0190 
0191 template <class T, class = std::enable_if_t<is_sequence_of_axis<std::decay_t<T>>::value>>
0192 struct requires_sequence_of_axis {};
0193 
0194 template <class T,
0195           class = std::enable_if_t<is_sequence_of_axis_variant<std::decay_t<T>>::value>>
0196 struct requires_sequence_of_axis_variant {};
0197 
0198 template <class T,
0199           class = std::enable_if_t<is_sequence_of_any_axis<std::decay_t<T>>::value>>
0200 struct requires_sequence_of_any_axis {};
0201 
0202 template <class T,
0203           class = std::enable_if_t<is_any_axis<mp11::mp_first<std::decay_t<T>>>::value>>
0204 struct requires_axes {};
0205 
0206 template <class T, class U,
0207           class = std::enable_if_t<is_transform<std::decay_t<T>, U>::value>>
0208 struct requires_transform {};
0209 
0210 template <class T, class = std::enable_if_t<is_allocator<std::decay_t<T>>::value>>
0211 struct requires_allocator {};
0212 
0213 } // namespace detail
0214 } // namespace histogram
0215 } // namespace boost
0216 
0217 #endif