Skip to content

Commit

Permalink
Merge 9366ed8 into a819ef5
Browse files Browse the repository at this point in the history
  • Loading branch information
HDembinski committed Jun 7, 2020
2 parents a819ef5 + 9366ed8 commit 9e4a51e
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 189 deletions.
11 changes: 4 additions & 7 deletions include/boost/histogram/axis/polymorphic_bin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
#ifndef BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
#define BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP

#include <boost/histogram/detail/detect.hpp>
#include <type_traits>

namespace boost {
namespace histogram {
namespace axis {
Expand Down Expand Up @@ -53,7 +50,7 @@ class polymorphic_bin {

template <class BinType>
bool operator==(const BinType& rhs) const noexcept {
return equal_impl(detail::has_method_lower<BinType>(), rhs);
return equal_impl(rhs, 0);
}

template <class BinType>
Expand All @@ -65,17 +62,17 @@ class polymorphic_bin {
bool is_discrete() const noexcept { return lower_or_value_ == upper_; }

private:
bool equal_impl(std::true_type, const polymorphic_bin& rhs) const noexcept {
bool equal_impl(const polymorphic_bin& rhs, int) const noexcept {
return lower_or_value_ == rhs.lower_or_value_ && upper_ == rhs.upper_;
}

template <class BinType>
bool equal_impl(std::true_type, const BinType& rhs) const noexcept {
auto equal_impl(const BinType& rhs, decltype(rhs.lower(), 0)) const noexcept {
return lower() == rhs.lower() && upper() == rhs.upper();
}

template <class BinType>
bool equal_impl(std::false_type, const BinType& rhs) const noexcept {
bool equal_impl(const BinType& rhs, float) const noexcept {
return is_discrete() && static_cast<value_type>(*this) == rhs;
}

Expand Down
19 changes: 13 additions & 6 deletions include/boost/histogram/axis/traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ namespace boost {
namespace histogram {
namespace detail {

static axis::null_type null_value;

template <class Axis>
struct value_type_deducer {
using type =
Expand Down Expand Up @@ -73,8 +75,6 @@ double value_method_switch(I&&, D&&, const A&, priority<0>) {
double{};
}

static axis::null_type null_value;

struct variant_access {
template <class T, class Variant>
static auto get_if(Variant* v) noexcept {
Expand Down Expand Up @@ -108,6 +108,16 @@ struct variant_access {
}
};

template <class A>
decltype(auto) metadata_impl(A&& a, decltype(a.metadata(), 0)) {
return std::forward<A>(a).metadata();
}

template <class A>
axis::null_type& metadata_impl(A&&, float) {
return detail::null_value;
}

} // namespace detail

namespace axis {
Expand Down Expand Up @@ -338,10 +348,7 @@ index_type extent(const Axis& axis) noexcept {
*/
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&&) -> axis::null_type& { return detail::null_value; },
std::forward<Axis>(axis));
return detail::metadata_impl(std::forward<Axis>(axis), 0);
}

/** Returns axis value for index.
Expand Down
118 changes: 52 additions & 66 deletions include/boost/histogram/detail/detect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
#define BOOST_HISTOGRAM_DETAIL_DETECT_HPP

#include <boost/histogram/fwd.hpp>
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/function.hpp>
#include <boost/mp11/utility.hpp>
#include <boost/mp11/function.hpp> // mp_and, mp_or
#include <boost/mp11/integral.hpp> // mp_not
#include <boost/mp11/list.hpp> // mp_first
#include <iterator>
#include <tuple>
#include <type_traits>
Expand All @@ -27,79 +27,68 @@ namespace boost {
namespace histogram {
namespace detail {

#define BOOST_HISTOGRAM_DETAIL_DETECT(name, cond) \
template <class T> \
using name##_impl = decltype(cond); \
template <class T> \
using name = typename boost::mp11::mp_valid<name##_impl, T>::type

#define BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(name, cond) \
template <class T, class U> \
using name##_impl = decltype(cond); \
template <class T, class U = T> \
using name = typename boost::mp11::mp_valid<name##_impl, T, U>::type

// metadata has overloads, trying to get pmf in this case always fails
BOOST_HISTOGRAM_DETAIL_DETECT(has_method_metadata, (std::declval<T&>().metadata()));

// resize has overloads, trying to get pmf in this case always fails
BOOST_HISTOGRAM_DETAIL_DETECT(has_method_resize, (std::declval<T&>().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);
#define BOOST_HISTOGRAM_DETAIL_DETECT(name, cond) \
template <class U> \
struct name##_impl { \
typedef char yes[1]; \
typedef char no[2]; \
template <class T> \
static yes& test(T& t, decltype(cond, 0)); \
template <class T> \
static no& test(T&, float); \
using type = \
std::integral_constant<bool, (sizeof(test(std::declval<U&>(), 0)) == 1)>; \
}; \
template <class T> \
using name = typename name##_impl<T>::type

#define BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(name, cond) \
template <class V, class W> \
struct name##_impl { \
typedef char yes[1]; \
typedef char no[2]; \
template <class T, class U> \
static yes& test(decltype(cond, 0)); \
template <class, class> \
static no& test(float); \
using type = std::integral_constant<bool, (sizeof(test<V, W>(0)) == 1)>; \
}; \
template <class T, class U = T> \
using name = typename name##_impl<T, U>::type

// reset has overloads, trying to get pmf in this case always fails
BOOST_HISTOGRAM_DETAIL_DETECT(has_method_reset, (std::declval<T>().reset(0)));

BOOST_HISTOGRAM_DETAIL_DETECT(has_method_options, &T::options);
BOOST_HISTOGRAM_DETAIL_DETECT(has_method_reset, t.reset(0));

BOOST_HISTOGRAM_DETAIL_DETECT(has_allocator, &T::get_allocator);

BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable, (std::declval<T&>()[0]));
BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable, t[0]);

BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(
is_transform,
(std::declval<T&>().inverse(std::declval<T&>().forward(std::declval<U>()))));

BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable_container, (std::declval<T>()[0], &T::size,
std::begin(std::declval<T>()),
std::end(std::declval<T>())));
BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable_container,
(t[0], t.size(), std::begin(t), std::end(t)));

BOOST_HISTOGRAM_DETAIL_DETECT(is_vector_like,
(std::declval<T>()[0], &T::size,
std::declval<T>().resize(0), std::begin(std::declval<T>()),
std::end(std::declval<T>())));
(t[0], t.size(), t.resize(0), std::begin(t), std::end(t)));

BOOST_HISTOGRAM_DETAIL_DETECT(is_array_like,
(std::declval<T>()[0], &T::size, std::tuple_size<T>::value,
std::begin(std::declval<T>()),
std::end(std::declval<T>())));
BOOST_HISTOGRAM_DETAIL_DETECT(is_array_like, (t[0], t.size(), std::tuple_size<T>::value,
std::begin(t), std::end(t)));

BOOST_HISTOGRAM_DETAIL_DETECT(is_map_like, (std::declval<typename T::key_type>(),
std::declval<typename T::mapped_type>(),
std::begin(std::declval<T>()),
std::end(std::declval<T>())));
BOOST_HISTOGRAM_DETAIL_DETECT(is_map_like, ((typename T::key_type*)nullptr,
(typename T::mapped_type*)nullptr,
std::begin(t), std::end(t)));

// 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_axis, (t.size(), &T::index));

BOOST_HISTOGRAM_DETAIL_DETECT(is_iterable, (std::begin(std::declval<T&>()),
std::end(std::declval<T&>())));
BOOST_HISTOGRAM_DETAIL_DETECT(is_iterable, (std::begin(t), std::end(t)));

BOOST_HISTOGRAM_DETAIL_DETECT(is_iterator,
(typename std::iterator_traits<T>::iterator_category()));
(typename std::iterator_traits<T>::iterator_category{}));

BOOST_HISTOGRAM_DETAIL_DETECT(is_streamable,
(std::declval<std::ostream&>() << std::declval<T&>()));
BOOST_HISTOGRAM_DETAIL_DETECT(is_streamable, (std::declval<std::ostream&>() << t));

BOOST_HISTOGRAM_DETAIL_DETECT(has_operator_preincrement, (++std::declval<T&>()));
BOOST_HISTOGRAM_DETAIL_DETECT(has_operator_preincrement, ++t);

BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_equal, (std::declval<const T&>() ==
std::declval<const U>()));
Expand Down Expand Up @@ -131,28 +120,28 @@ using is_adaptible =
mp11::mp_or<is_vector_like<T>, is_array_like<T>, is_map_like<T>>>;

template <class T>
struct is_tuple_impl : mp11::mp_false {};
struct is_tuple_impl : std::false_type {};

template <class... Ts>
struct is_tuple_impl<std::tuple<Ts...>> : mp11::mp_true {};
struct is_tuple_impl<std::tuple<Ts...>> : std::true_type {};

template <class T>
using is_tuple = typename is_tuple_impl<T>::type;

template <class T>
struct is_variant_impl : mp11::mp_false {};
struct is_variant_impl : std::false_type {};

template <class... Ts>
struct is_variant_impl<boost::variant2::variant<Ts...>> : mp11::mp_true {};
struct is_variant_impl<boost::variant2::variant<Ts...>> : std::true_type {};

template <class T>
using is_variant = typename is_variant_impl<T>::type;

template <class T>
struct is_axis_variant_impl : mp11::mp_false {};
struct is_axis_variant_impl : std::false_type {};

template <class... Ts>
struct is_axis_variant_impl<axis::variant<Ts...>> : mp11::mp_true {};
struct is_axis_variant_impl<axis::variant<Ts...>> : std::true_type {};

template <class T>
using is_axis_variant = typename is_axis_variant_impl<T>::type;
Expand Down Expand Up @@ -207,9 +196,6 @@ template <class T,
class = std::enable_if_t<is_any_axis<mp11::mp_first<std::decay_t<T>>>::value>>
struct requires_axes {};

template <class T, class U, class = std::enable_if_t<std::is_convertible<T, U>::value>>
struct requires_convertible {};

template <class T, class U,
class = std::enable_if_t<is_transform<std::decay_t<T>, U>::value>>
struct requires_transform {};
Expand Down
18 changes: 12 additions & 6 deletions include/boost/histogram/detail/make_default.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@
#ifndef BOOST_HISTOGRAM_DETAIL_MAKE_DEFAULT_HPP
#define BOOST_HISTOGRAM_DETAIL_MAKE_DEFAULT_HPP

#include <boost/histogram/detail/detect.hpp>
#include <boost/histogram/detail/static_if.hpp>

namespace boost {
namespace histogram {
namespace detail {

template <class T>
auto make_default(const T& t) {
return static_if<has_allocator<T>>([](const auto& t) { return T(t.get_allocator()); },
[](const auto&) { return T{}; }, t);
T make_default_impl(const T& t, decltype(t.get_allocator(), 0)) {
return T(t.get_allocator());
}

template <class T>
T make_default_impl(const T&, float) {
return T{};
}

template <class T>
T make_default(const T& t) {
return make_default_impl(t, 0);
}

} // namespace detail
Expand Down
3 changes: 2 additions & 1 deletion include/boost/histogram/storage_adaptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@ struct map_impl : T {
struct iterator_t
: iterator_adaptor<iterator_t<Value, Reference, MapPtr>, std::size_t, Reference> {
iterator_t() = default;
template <class V, class R, class M, class = requires_convertible<M, MapPtr>>
template <class V, class R, class M,
class = std::enable_if_t<std::is_convertible<M, MapPtr>::value>>
iterator_t(const iterator_t<V, R, M>& it) noexcept : iterator_t(it.map_, it.base()) {}
iterator_t(MapPtr m, std::size_t i) noexcept
: iterator_t::iterator_adaptor_(i), map_(m) {}
Expand Down

0 comments on commit 9e4a51e

Please sign in to comment.