1 // Copyright 2019 Hans Dembinski
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
7 #ifndef BOOST_HISTOGRAM_DETAIL_ACCUMULATOR_TRAITS_HPP
8 #define BOOST_HISTOGRAM_DETAIL_ACCUMULATOR_TRAITS_HPP
10 #include <boost/histogram/detail/priority.hpp>
11 #include <boost/histogram/fwd.hpp>
13 #include <type_traits>
17 // forward declare accumulator_set so that it can be matched below
18 namespace accumulators {
19 template <class, class, class>
20 struct accumulator_set;
26 template <bool WeightSupport, class... Ts>
27 struct accumulator_traits_holder {
28 static constexpr bool weight_support = WeightSupport;
29 using args = std::tuple<Ts...>;
32 // member function pointer with weight_type as first argument is better match
33 template <class R, class T, class U, class... Ts>
34 accumulator_traits_holder<true, Ts...> accumulator_traits_impl_call_op(
35 R (T::*)(boost::histogram::weight_type<U>, Ts...));
37 template <class R, class T, class U, class... Ts>
38 accumulator_traits_holder<true, Ts...> accumulator_traits_impl_call_op(
39 R (T::*)(boost::histogram::weight_type<U>&, Ts...));
41 template <class R, class T, class U, class... Ts>
42 accumulator_traits_holder<true, Ts...> accumulator_traits_impl_call_op(
43 R (T::*)(boost::histogram::weight_type<U>&&, Ts...));
45 template <class R, class T, class U, class... Ts>
46 accumulator_traits_holder<true, Ts...> accumulator_traits_impl_call_op(
47 R (T::*)(const boost::histogram::weight_type<U>&, Ts...));
49 // member function pointer only considered if all specializations above fail
50 template <class R, class T, class... Ts>
51 accumulator_traits_holder<false, Ts...> accumulator_traits_impl_call_op(R (T::*)(Ts...));
54 auto accumulator_traits_impl(T&, priority<1>)
55 -> decltype(accumulator_traits_impl_call_op(&T::operator()));
58 auto accumulator_traits_impl(T&, priority<1>)
59 -> decltype(std::declval<T&>() += 0, accumulator_traits_holder<true>{});
62 auto accumulator_traits_impl(T&, priority<0>) -> accumulator_traits_holder<false>;
64 // for boost.accumulators compatibility
65 template <class S, class F, class W>
66 accumulator_traits_holder<false, S> accumulator_traits_impl(
67 boost::accumulators::accumulator_set<S, F, W>&, priority<1>) {
68 static_assert(std::is_same<W, void>::value,
69 "accumulator_set with weights is not directly supported, please use "
70 "a wrapper class that implements the Accumulator concept");
74 using accumulator_traits =
75 decltype(accumulator_traits_impl(std::declval<T&>(), priority<1>{}));
78 } // namespace histogram