1 // Copyright 2018 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_AXIS_POLYMORPHIC_BIN_HPP
8 #define BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
10 #include <boost/histogram/detail/detect.hpp>
11 #include <type_traits>
18 Holds the bin data of an axis::variant.
20 The interface is a superset of the axis::interval_view
21 class. In addition, the object is implicitly convertible to the value type,
22 returning the equivalent of a call to lower(). For discrete axes, lower() ==
23 upper(), and width() returns zero.
25 This is not a view like axis::interval_view for two reasons.
26 - Sequential calls to lower() and upper() would have to each loop through
27 the variant types. This is likely to be slower than filling all the data in
29 - polymorphic_bin may be created from a temporary instance of axis::variant,
30 like in the call histogram::axis(0). Storing a reference to the axis would
31 result in a dangling reference. Rather than specialing the code to handle
32 this, it seems easier to just use a value instead of a view.
34 template <typename RealType>
35 class polymorphic_bin {
36 using value_type = RealType;
39 polymorphic_bin(value_type lower, value_type upper)
40 : lower_or_value_(lower), upper_(upper) {}
42 /// Implicitly convert to bin value (for axis with discrete values).
43 operator const value_type&() const noexcept { return lower_or_value_; }
45 /// Return lower edge of bin.
46 value_type lower() const noexcept { return lower_or_value_; }
47 /// Return upper edge of bin.
48 value_type upper() const noexcept { return upper_; }
49 /// Return center of bin.
50 value_type center() const noexcept { return 0.5 * (lower() + upper()); }
51 /// Return width of bin.
52 value_type width() const noexcept { return upper() - lower(); }
54 template <typename BinType>
55 bool operator==(const BinType& rhs) const noexcept {
56 return equal_impl(detail::has_method_lower<BinType>(), rhs);
59 template <typename BinType>
60 bool operator!=(const BinType& rhs) const noexcept {
61 return !operator==(rhs);
64 /// Return true if bin is discrete.
65 bool is_discrete() const noexcept { return lower_or_value_ == upper_; }
68 bool equal_impl(std::true_type, const polymorphic_bin& rhs) const noexcept {
69 return lower_or_value_ == rhs.lower_or_value_ && upper_ == rhs.upper_;
72 template <typename BinType>
73 bool equal_impl(std::true_type, const BinType& rhs) const noexcept {
74 return lower() == rhs.lower() && upper() == rhs.upper();
77 template <typename BinType>
78 bool equal_impl(std::false_type, const BinType& rhs) const noexcept {
79 return is_discrete() && static_cast<value_type>(*this) == rhs;
82 const value_type lower_or_value_, upper_;
86 } // namespace histogram