// Copyright 2015-2019 Hans Dembinski // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_HISTOGRAM_DETAIL_DETECT_HPP #define BOOST_HISTOGRAM_DETAIL_DETECT_HPP #include #include #include #include #include #include #include #include namespace boost { namespace histogram { namespace detail { #define BOOST_HISTOGRAM_DETAIL_DETECT(name, cond) \ template \ using name##_impl = decltype(cond); \ template \ using name = typename boost::mp11::mp_valid::type #define BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(name, cond) \ template \ using name##_impl = decltype(cond); \ template \ using name = typename boost::mp11::mp_valid::type // metadata has overloads, trying to get pmf in this case always fails BOOST_HISTOGRAM_DETAIL_DETECT(has_method_metadata, (std::declval().metadata())); // resize has overloads, trying to get pmf in this case always fails BOOST_HISTOGRAM_DETAIL_DETECT(has_method_resize, (std::declval().resize(0))); BOOST_HISTOGRAM_DETAIL_DETECT(has_method_size, &T::size); BOOST_HISTOGRAM_DETAIL_DETECT(has_method_clear, &T::clear); BOOST_HISTOGRAM_DETAIL_DETECT(has_method_lower, &T::lower); BOOST_HISTOGRAM_DETAIL_DETECT(has_method_value, &T::value); BOOST_HISTOGRAM_DETAIL_DETECT(has_method_update, &T::update); // reset has overloads, trying to get pmf in this case always fails BOOST_HISTOGRAM_DETAIL_DETECT(has_method_reset, (std::declval().reset(0))); BOOST_HISTOGRAM_DETAIL_DETECT(has_method_options, &T::options); BOOST_HISTOGRAM_DETAIL_DETECT(has_allocator, &T::get_allocator); BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable, (std::declval()[0])); BOOST_HISTOGRAM_DETAIL_DETECT_BINARY( is_transform, (std::declval().inverse(std::declval().forward(std::declval())))); BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable_container, (std::declval()[0], &T::size, std::begin(std::declval()), std::end(std::declval()))); BOOST_HISTOGRAM_DETAIL_DETECT(is_vector_like, (std::declval()[0], &T::size, std::declval().resize(0), std::begin(std::declval()), std::end(std::declval()))); BOOST_HISTOGRAM_DETAIL_DETECT(is_array_like, (std::declval()[0], &T::size, std::tuple_size::value, std::begin(std::declval()), std::end(std::declval()))); BOOST_HISTOGRAM_DETAIL_DETECT(is_map_like, (std::declval(), std::declval(), std::begin(std::declval()), std::end(std::declval()))); // ok: is_axis is false for axis::variant, because T::index is templated BOOST_HISTOGRAM_DETAIL_DETECT(is_axis, (&T::size, &T::index)); BOOST_HISTOGRAM_DETAIL_DETECT(is_iterable, (std::begin(std::declval()), std::end(std::declval()))); BOOST_HISTOGRAM_DETAIL_DETECT(is_iterator, (typename std::iterator_traits::iterator_category())); BOOST_HISTOGRAM_DETAIL_DETECT(is_streamable, (std::declval() << std::declval())); BOOST_HISTOGRAM_DETAIL_DETECT(has_operator_preincrement, (++std::declval())); BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_equal, (std::declval() == std::declval())); BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_radd, (std::declval() += std::declval())); BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rsub, (std::declval() -= std::declval())); BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rmul, (std::declval() *= std::declval())); BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rdiv, (std::declval() /= std::declval())); BOOST_HISTOGRAM_DETAIL_DETECT_BINARY( has_method_eq, (std::declval().operator==(std::declval()))); BOOST_HISTOGRAM_DETAIL_DETECT(has_threading_support, (T::has_threading_support)); template using is_storage = mp11::mp_and, has_method_reset, has_threading_support>; template using is_adaptible = mp11::mp_and>, mp11::mp_or, is_array_like, is_map_like>>; template struct is_tuple_impl : mp11::mp_false {}; template struct is_tuple_impl> : mp11::mp_true {}; template using is_tuple = typename is_tuple_impl::type; template struct is_variant_impl : mp11::mp_false {}; template struct is_variant_impl> : mp11::mp_true {}; template using is_variant = typename is_variant_impl::type; template struct is_axis_variant_impl : mp11::mp_false {}; template struct is_axis_variant_impl> : mp11::mp_true {}; template using is_axis_variant = typename is_axis_variant_impl::type; template using is_any_axis = mp11::mp_or, is_axis_variant>; template using is_sequence_of_axis = mp11::mp_and, is_axis>>; template using is_sequence_of_axis_variant = mp11::mp_and, is_axis_variant>>; template using is_sequence_of_any_axis = mp11::mp_and, is_any_axis>>; // poor-mans concept checks template >::value>> struct requires_storage {}; template , class = std::enable_if_t<(is_storage<_>::value || is_adaptible<_>::value)>> struct requires_storage_or_adaptible {}; template >::value>> struct requires_iterator {}; template >>::value>> struct requires_iterable {}; template >::value>> struct requires_axis {}; template >::value>> struct requires_any_axis {}; template >::value>> struct requires_sequence_of_axis {}; template >::value>> struct requires_sequence_of_axis_variant {}; template >::value>> struct requires_sequence_of_any_axis {}; template >>::value>> struct requires_axes {}; template ::value>> struct requires_convertible {}; template , U>::value>> struct requires_transform {}; } // namespace detail } // namespace histogram } // namespace boost #endif