mirror of
https://github.com/boostorg/histogram.git
synced 2026-01-19 04:12:12 +00:00
update axis::traits (#217)
* added traits:::is_continuous, traits::value_type * use of static_options on qualified types is now invalid
This commit is contained in:
@@ -40,7 +40,7 @@ namespace axis {
|
||||
template <class Value, class MetaData, class Options>
|
||||
class integer : public iterator_mixin<integer<Value, MetaData, Options>> {
|
||||
static_assert(std::is_integral<Value>::value || std::is_floating_point<Value>::value,
|
||||
"integer axis requires type floating point or integral type");
|
||||
"integer axis requires floating point or integral type");
|
||||
|
||||
using value_type = Value;
|
||||
using local_index_type = std::conditional_t<std::is_integral<value_type>::value,
|
||||
|
||||
@@ -28,7 +28,17 @@ namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
using static_options_impl = axis::option::bitset<T::options()>;
|
||||
using get_options_from_method = axis::option::bitset<T::options()>;
|
||||
|
||||
template <class Axis>
|
||||
struct static_options_impl {
|
||||
static_assert(std::is_same<std::decay_t<Axis>, Axis>::value,
|
||||
"support of static_options for qualified types was removed, please use "
|
||||
"static_options<std::decay_t<...>>");
|
||||
using type = mp11::mp_eval_or<
|
||||
mp11::mp_if<has_method_update<Axis>, axis::option::growth_t, axis::option::none_t>,
|
||||
get_options_from_method, Axis>;
|
||||
};
|
||||
|
||||
template <class I, class D, class A>
|
||||
double value_method_switch_impl1(std::false_type, I&&, D&&, const A&) {
|
||||
@@ -97,29 +107,51 @@ struct variant_access {
|
||||
namespace axis {
|
||||
namespace traits {
|
||||
|
||||
/** Returns reference to metadata of an axis.
|
||||
/** Get value type for axis type.
|
||||
|
||||
If the expression x.metadata() for an axis instance `x` (maybe const) is valid, return
|
||||
the result. Otherwise, return a reference to a static instance of
|
||||
boost::histogram::axis::null_type.
|
||||
|
||||
@param axis any axis instance
|
||||
Doxygen does not render this well. This is a meta-function (alias template), it accepts
|
||||
an axis type and returns the value type.
|
||||
*/
|
||||
template <class Axis>
|
||||
decltype(auto) metadata(Axis&& axis) noexcept {
|
||||
return detail::static_if<detail::has_method_metadata<std::decay_t<Axis>>>(
|
||||
[](auto&& a) -> decltype(auto) { return a.metadata(); },
|
||||
[](auto &&) -> mp11::mp_if<std::is_const<std::remove_reference_t<Axis>>,
|
||||
axis::null_type const&, axis::null_type&> {
|
||||
return detail::null_value;
|
||||
},
|
||||
std::forward<Axis>(axis));
|
||||
}
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
using value_type = std::decay_t<decltype(std::declval<Axis>().value(0))>;
|
||||
#else
|
||||
struct value_type;
|
||||
#endif
|
||||
|
||||
/** Whether axis is continuous or discrete.
|
||||
|
||||
Doxygen does not render this well. This is a meta-function (alias template), it accepts
|
||||
an axis type and returns a compile-time boolean. If the boolean is true, the axis is
|
||||
continuous. Otherwise it is discrete.
|
||||
*/
|
||||
template <class Axis>
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
using is_continuous = typename std::is_floating_point<traits::value_type<Axis>>::type;
|
||||
#else
|
||||
struct is_continuous;
|
||||
#endif
|
||||
|
||||
/** Meta-function to detect whether an axis is reducible.
|
||||
|
||||
Doxygen does not render this well. This is a meta-function (alias template), it accepts
|
||||
an axis type and represents compile-time boolean which is true or false, depending on
|
||||
whether the axis can be reduced with boost::histogram::algorithm::reduce().
|
||||
|
||||
@tparam Axis axis type.
|
||||
*/
|
||||
template <class Axis>
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
using is_reducible = std::is_constructible<Axis, const Axis&, axis::index_type,
|
||||
axis::index_type, unsigned>;
|
||||
#else
|
||||
struct is_reducible;
|
||||
#endif
|
||||
|
||||
/** Get static axis options for axis type.
|
||||
|
||||
Doxygen does not render this well. This is a meta-function, it accepts an axis
|
||||
type and represents its boost::histogram::axis::option::bitset.
|
||||
Doxygen does not render this well. This is a meta-function (alias template), it accepts
|
||||
an axis type and returns the boost::histogram::axis::option::bitset.
|
||||
|
||||
If Axis::options() is valid and constexpr, static_options is the corresponding
|
||||
option type. Otherwise, it is boost::histogram::axis::option::growth_t, if the
|
||||
@@ -129,10 +161,7 @@ decltype(auto) metadata(Axis&& axis) noexcept {
|
||||
*/
|
||||
template <class Axis>
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
using static_options =
|
||||
mp11::mp_eval_or<mp11::mp_if<detail::has_method_update<std::decay_t<Axis>>,
|
||||
option::growth_t, option::none_t>,
|
||||
detail::static_options_impl, std::decay_t<Axis>>;
|
||||
using static_options = typename detail::static_options_impl<Axis>::type;
|
||||
#else
|
||||
struct static_options;
|
||||
#endif
|
||||
@@ -163,6 +192,25 @@ constexpr index_type extent(const Axis& axis) noexcept {
|
||||
(opt & option::overflow ? 1 : 0);
|
||||
}
|
||||
|
||||
/** Returns reference to metadata of an axis.
|
||||
|
||||
If the expression x.metadata() for an axis instance `x` (maybe const) is valid, return
|
||||
the result. Otherwise, return a reference to a static instance of
|
||||
boost::histogram::axis::null_type.
|
||||
|
||||
@param axis any axis instance
|
||||
*/
|
||||
template <class Axis>
|
||||
decltype(auto) metadata(Axis&& axis) noexcept {
|
||||
return detail::static_if<detail::has_method_metadata<std::decay_t<Axis>>>(
|
||||
[](auto&& a) -> decltype(auto) { return a.metadata(); },
|
||||
[](auto &&) -> mp11::mp_if<std::is_const<std::remove_reference_t<Axis>>,
|
||||
axis::null_type const&, axis::null_type&> {
|
||||
return detail::null_value;
|
||||
},
|
||||
std::forward<Axis>(axis));
|
||||
}
|
||||
|
||||
/** Returns axis value for index.
|
||||
|
||||
If the axis has no `value` method, throw std::runtime_error. If the method exists and
|
||||
@@ -298,22 +346,6 @@ Result width_as(const Axis& axis, index_type index) {
|
||||
axis);
|
||||
}
|
||||
|
||||
/** Meta-function to detect whether an axis is reducible.
|
||||
|
||||
Doxygen does not render this well. This is a meta-function, it accepts an axis
|
||||
type and represents std::true_type or std::false_type, depending on whether the axis can
|
||||
be reduced with boost::histogram::algorithm::reduce().
|
||||
|
||||
@tparam Axis axis type.
|
||||
*/
|
||||
template <class Axis>
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
using is_reducible = std::is_constructible<Axis, const Axis&, axis::index_type,
|
||||
axis::index_type, unsigned>;
|
||||
#else
|
||||
struct is_reducible;
|
||||
#endif
|
||||
|
||||
} // namespace traits
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
|
||||
@@ -89,7 +89,7 @@ struct storage_grower {
|
||||
auto sit = shifts;
|
||||
auto dit = data_;
|
||||
for_each_axis(axes_, [&](const auto& a) {
|
||||
using opt = axis::traits::static_options<decltype(a)>;
|
||||
using opt = axis::traits::static_options<std::decay_t<decltype(a)>>;
|
||||
if (opt::test(axis::option::underflow)) {
|
||||
if (dit->idx == 0) {
|
||||
// axis has underflow and we are in the underflow bin:
|
||||
|
||||
@@ -294,7 +294,7 @@ public:
|
||||
const auto clast = ca + begin_.indices_.hist_->rank() - 1;
|
||||
begin_.indices_.hist_->for_each_axis(
|
||||
[ca, clast, cov, &stride, this](const auto& a) mutable {
|
||||
using opt = axis::traits::static_options<decltype(a)>;
|
||||
using opt = axis::traits::static_options<std::decay_t<decltype(a)>>;
|
||||
constexpr int under = opt::test(axis::option::underflow);
|
||||
constexpr int over = opt::test(axis::option::overflow);
|
||||
const auto size = a.size();
|
||||
|
||||
@@ -16,6 +16,38 @@
|
||||
using namespace boost::histogram::axis;
|
||||
|
||||
int main() {
|
||||
// value_type
|
||||
{
|
||||
BOOST_TEST_TRAIT_SAME(traits::value_type<integer<int>>, int);
|
||||
BOOST_TEST_TRAIT_SAME(traits::value_type<category<int>>, int);
|
||||
BOOST_TEST_TRAIT_SAME(traits::value_type<regular<double>>, double);
|
||||
}
|
||||
|
||||
// is_continuous
|
||||
{
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_continuous<regular<>>));
|
||||
BOOST_TEST_TRAIT_FALSE((traits::is_continuous<integer<int>>));
|
||||
BOOST_TEST_TRAIT_FALSE((traits::is_continuous<category<int>>));
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_continuous<integer<double>>));
|
||||
}
|
||||
|
||||
// is_reducible
|
||||
{
|
||||
struct not_reducible {};
|
||||
struct reducible {
|
||||
reducible(const reducible&, index_type, index_type, unsigned);
|
||||
};
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_reducible<reducible>));
|
||||
BOOST_TEST_TRAIT_FALSE((traits::is_reducible<not_reducible>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_reducible<regular<>>));
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_reducible<variable<>>));
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_reducible<circular<>>));
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_reducible<integer<>>));
|
||||
BOOST_TEST_TRAIT_FALSE((traits::is_reducible<category<>>));
|
||||
}
|
||||
|
||||
// index, rank, value, width
|
||||
{
|
||||
auto a = integer<>(1, 3);
|
||||
@@ -30,10 +62,7 @@ int main() {
|
||||
BOOST_TEST_EQ(traits::rank(b), 1);
|
||||
BOOST_TEST_EQ(traits::value(b, 0), 1);
|
||||
BOOST_TEST_EQ(traits::width(b, 0), 1);
|
||||
auto& b1 = b;
|
||||
BOOST_TEST(traits::static_options<decltype(b1)>::test(option::underflow));
|
||||
const auto& b2 = b;
|
||||
BOOST_TEST(traits::static_options<decltype(b2)>::test(option::underflow));
|
||||
BOOST_TEST(traits::static_options<decltype(b)>::test(option::underflow));
|
||||
|
||||
auto c = category<std::string>{"red", "blue"};
|
||||
BOOST_TEST_EQ(traits::index(c, "blue"), 1);
|
||||
@@ -61,8 +90,6 @@ int main() {
|
||||
{
|
||||
using A = integer<>;
|
||||
BOOST_TEST_EQ(traits::static_options<A>::test(option::growth), false);
|
||||
BOOST_TEST_EQ(traits::static_options<A&>::test(option::growth), false);
|
||||
BOOST_TEST_EQ(traits::static_options<const A&>::test(option::growth), false);
|
||||
auto expected = option::underflow | option::overflow;
|
||||
auto a = A{};
|
||||
BOOST_TEST_EQ(traits::options(a), expected);
|
||||
@@ -72,8 +99,6 @@ int main() {
|
||||
|
||||
using B = integer<int, null_type, option::growth_t>;
|
||||
BOOST_TEST_EQ(traits::static_options<B>::test(option::growth), true);
|
||||
BOOST_TEST_EQ(traits::static_options<B&>::test(option::growth), true);
|
||||
BOOST_TEST_EQ(traits::static_options<const B&>::test(option::growth), true);
|
||||
BOOST_TEST_EQ(traits::options(B{}), option::growth);
|
||||
|
||||
struct growing {
|
||||
@@ -81,8 +106,6 @@ int main() {
|
||||
};
|
||||
using C = growing;
|
||||
BOOST_TEST_EQ(traits::static_options<C>::test(option::growth), true);
|
||||
BOOST_TEST_EQ(traits::static_options<C&>::test(option::growth), true);
|
||||
BOOST_TEST_EQ(traits::static_options<const C&>::test(option::growth), true);
|
||||
auto c = C{};
|
||||
BOOST_TEST_EQ(traits::options(c), option::growth);
|
||||
BOOST_TEST_EQ(traits::options(static_cast<C&>(c)), option::growth);
|
||||
@@ -94,8 +117,6 @@ int main() {
|
||||
};
|
||||
using D = notgrowing;
|
||||
BOOST_TEST_EQ(traits::static_options<D>::test(option::growth), false);
|
||||
BOOST_TEST_EQ(traits::static_options<D&>::test(option::growth), false);
|
||||
BOOST_TEST_EQ(traits::static_options<const D&>::test(option::growth), false);
|
||||
auto d = D{};
|
||||
BOOST_TEST_EQ(traits::options(d), option::none);
|
||||
BOOST_TEST_EQ(traits::options(static_cast<D&>(d)), option::none);
|
||||
@@ -146,22 +167,5 @@ int main() {
|
||||
BOOST_TEST_EQ(traits::metadata(static_cast<const Both&>(b)), 0);
|
||||
}
|
||||
|
||||
// is_reducible
|
||||
{
|
||||
struct not_reducible {};
|
||||
struct reducible {
|
||||
reducible(const reducible&, index_type, index_type, unsigned);
|
||||
};
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_reducible<reducible>));
|
||||
BOOST_TEST_TRAIT_FALSE((traits::is_reducible<not_reducible>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_reducible<regular<>>));
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_reducible<variable<>>));
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_reducible<circular<>>));
|
||||
BOOST_TEST_TRAIT_TRUE((traits::is_reducible<integer<>>));
|
||||
BOOST_TEST_TRAIT_FALSE((traits::is_reducible<category<>>));
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user