mirror of
https://github.com/boostorg/histogram.git
synced 2026-02-19 14:32:12 +00:00
use std::enable_if_t for check, to get better error messages
This commit is contained in:
@@ -201,6 +201,9 @@ BOOST_HISTOGRAM_DETECT(is_axis, (&T::size, &T::operator()));
|
||||
BOOST_HISTOGRAM_DETECT(is_iterable,
|
||||
(std::begin(std::declval<T&>()), std::end(std::declval<T&>())));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_iterator,
|
||||
(typename std::iterator_traits<T>::iterator_category()));
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(is_streamable,
|
||||
(std::declval<std::ostream&>() << std::declval<T&>()));
|
||||
|
||||
@@ -269,34 +272,31 @@ template <typename T>
|
||||
using is_sample = is_sample_impl<naked<T>>;
|
||||
|
||||
// poor-mans concept checks
|
||||
template <class B>
|
||||
using requires = std::enable_if_t<B::value>;
|
||||
|
||||
template <class T, class = decltype(*std::declval<T&>(), ++std::declval<T&>())>
|
||||
template <class T, class = std::enable_if_t<is_iterator<naked<T>>::value>>
|
||||
struct requires_iterator {};
|
||||
|
||||
template <class T, class = requires<is_iterable<naked<T>>>>
|
||||
template <class T, class = std::enable_if_t<is_iterable<naked<T>>::value>>
|
||||
struct requires_iterable {};
|
||||
|
||||
template <class T, class = requires<is_axis<naked<T>>>>
|
||||
template <class T, class = std::enable_if_t<is_axis<naked<T>>::value>>
|
||||
struct requires_axis {};
|
||||
|
||||
template <class T, class = requires<is_any_axis<naked<T>>>>
|
||||
template <class T, class = std::enable_if_t<is_any_axis<naked<T>>::value>>
|
||||
struct requires_any_axis {};
|
||||
|
||||
template <class T, class = requires<is_sequence_of_axis<naked<T>>>>
|
||||
template <class T, class = std::enable_if_t<is_sequence_of_axis<naked<T>>::value>>
|
||||
struct requires_sequence_of_axis {};
|
||||
|
||||
template <class T, class = requires<is_sequence_of_axis_variant<naked<T>>>>
|
||||
template <class T, class = std::enable_if_t<is_sequence_of_axis_variant<naked<T>>::value>>
|
||||
struct requires_sequence_of_axis_variant {};
|
||||
|
||||
template <class T, class = requires<is_sequence_of_any_axis<naked<T>>>>
|
||||
template <class T, class = std::enable_if_t<is_sequence_of_any_axis<naked<T>>::value>>
|
||||
struct requires_sequence_of_any_axis {};
|
||||
|
||||
template <class T, class = requires<is_any_axis<mp11::mp_first<naked<T>>>>>
|
||||
template <class T, class = std::enable_if_t<is_any_axis<mp11::mp_first<naked<T>>>::value>>
|
||||
struct requires_axes {};
|
||||
|
||||
template <class T, class U, class = requires<std::is_convertible<T, U>>>
|
||||
template <class T, class U, class = std::enable_if_t<std::is_convertible<T, U>::value>>
|
||||
struct requires_convertible {};
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -26,17 +26,17 @@ namespace histogram {
|
||||
|
||||
/**
|
||||
Make histogram from compile-time axis configuration and custom storage.
|
||||
@param s Storage or container with standard interface (any vector, array, or map).
|
||||
@param storage Storage or container with standard interface (any vector, array, or map).
|
||||
@param axis First axis instance.
|
||||
@param axes Other axis instances.
|
||||
*/
|
||||
template <typename StorageOrContainer, typename T, typename... Ts,
|
||||
template <typename Storage, typename T, typename... Ts,
|
||||
typename = detail::requires_axis<T>>
|
||||
auto make_histogram_with(StorageOrContainer&& s, T&& axis, Ts&&... axes) {
|
||||
auto make_histogram_with(Storage&& storage, T&& axis, Ts&&... axes) {
|
||||
auto a = std::make_tuple(std::forward<T>(axis), std::forward<Ts>(axes)...);
|
||||
using U = detail::naked<StorageOrContainer>;
|
||||
using U = detail::naked<Storage>;
|
||||
using S = mp11::mp_if<detail::is_storage<U>, U, storage_adaptor<U>>;
|
||||
return histogram<decltype(a), S>(std::move(a), S(std::forward<StorageOrContainer>(s)));
|
||||
return histogram<decltype(a), S>(std::move(a), S(std::forward<Storage>(storage)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,50 +63,50 @@ auto make_weighted_histogram(T&& axis, Ts&&... axes) {
|
||||
|
||||
/**
|
||||
Make histogram from iterable range and custom storage.
|
||||
@param s Storage or container with standard interface (any vector, array, or map).
|
||||
@param c Iterable range of axis objects.
|
||||
@param storage Storage or container with standard interface (any vector, array, or map).
|
||||
@param iterable Iterable range of axis objects.
|
||||
*/
|
||||
template <typename StorageOrContainer, typename Iterable,
|
||||
template <typename Storage, typename Iterable,
|
||||
typename = detail::requires_sequence_of_any_axis<Iterable>>
|
||||
auto make_histogram_with(StorageOrContainer&& s, Iterable&& c) {
|
||||
using U = detail::naked<StorageOrContainer>;
|
||||
auto make_histogram_with(Storage&& storage, Iterable&& iterable) {
|
||||
using U = detail::naked<Storage>;
|
||||
using S = mp11::mp_if<detail::is_storage<U>, U, storage_adaptor<U>>;
|
||||
using It = detail::naked<Iterable>;
|
||||
using A = mp11::mp_if<detail::is_indexable_container<It>, It,
|
||||
boost::container::vector<mp11::mp_first<It>>>;
|
||||
return histogram<A, S>(std::forward<Iterable>(c),
|
||||
S(std::forward<StorageOrContainer>(s)));
|
||||
return histogram<A, S>(std::forward<Iterable>(iterable),
|
||||
S(std::forward<Storage>(storage)));
|
||||
}
|
||||
|
||||
/**
|
||||
Make histogram from iterable range and default storage.
|
||||
@param c Iterable range of axis objects.
|
||||
@param iterable Iterable range of axis objects.
|
||||
*/
|
||||
template <typename Iterable, typename = detail::requires_sequence_of_any_axis<Iterable>>
|
||||
auto make_histogram(Iterable&& c) {
|
||||
return make_histogram_with(default_storage(), std::forward<Iterable>(c));
|
||||
auto make_histogram(Iterable&& iterable) {
|
||||
return make_histogram_with(default_storage(), std::forward<Iterable>(iterable));
|
||||
}
|
||||
|
||||
/**
|
||||
Make histogram from iterable range and weight-counting storage.
|
||||
@param c Iterable range of axis objects.
|
||||
@param iterable Iterable range of axis objects.
|
||||
*/
|
||||
template <typename Iterable, typename = detail::requires_sequence_of_any_axis<Iterable>>
|
||||
auto make_weighted_histogram(Iterable&& c) {
|
||||
return make_histogram_with(weight_storage(), std::forward<Iterable>(c));
|
||||
auto make_weighted_histogram(Iterable&& iterable) {
|
||||
return make_histogram_with(weight_storage(), std::forward<Iterable>(iterable));
|
||||
}
|
||||
|
||||
/**
|
||||
Make histogram from iterator interval and custom storage.
|
||||
@param s Storage or container with standard interface (any vector, array, or map).
|
||||
@param storage Storage or container with standard interface (any vector, array, or map).
|
||||
@param begin Iterator to range of axis objects.
|
||||
@param end Iterator to range of axis objects.
|
||||
*/
|
||||
template <typename StorageOrContainer, typename Iterator,
|
||||
template <typename Storage, typename Iterator,
|
||||
typename = detail::requires_iterator<Iterator>>
|
||||
auto make_histogram_with(StorageOrContainer&& s, Iterator begin, Iterator end) {
|
||||
auto make_histogram_with(Storage&& storage, Iterator begin, Iterator end) {
|
||||
using T = detail::naked<decltype(*begin)>;
|
||||
return make_histogram_with(std::forward<StorageOrContainer>(s),
|
||||
return make_histogram_with(std::forward<Storage>(storage),
|
||||
boost::container::vector<T>(begin, end));
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,8 @@ struct map_impl : T {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U, class V = value_type, class = requires<has_operator_radd<V, U>>>
|
||||
template <class U, class V = value_type,
|
||||
class = std::enable_if_t<has_operator_radd<V, U>::value>>
|
||||
reference& operator+=(U&& u) {
|
||||
auto it = map->find(idx);
|
||||
if (it != static_cast<T*>(map)->end())
|
||||
@@ -132,7 +133,8 @@ struct map_impl : T {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class V = value_type, class = requires<has_operator_preincrement<V>>>
|
||||
template <class V = value_type,
|
||||
class = std::enable_if_t<has_operator_preincrement<V>::value>>
|
||||
reference& operator++() {
|
||||
auto it = map->find(idx);
|
||||
if (it != static_cast<T*>(map)->end())
|
||||
@@ -147,7 +149,7 @@ struct map_impl : T {
|
||||
return map->operator[](idx)(std::forward<Ts>(args)...);
|
||||
}
|
||||
|
||||
template <class V = value_type, class = requires<has_operator_rmul<V>>>
|
||||
template <class V = value_type, class = std::enable_if_t<has_operator_rmul<V>::value>>
|
||||
reference& operator*=(double x) {
|
||||
auto it = map->find(idx);
|
||||
if (it != static_cast<T*>(map)->end()) it->second *= x;
|
||||
@@ -264,7 +266,7 @@ public:
|
||||
}
|
||||
|
||||
template <class V = typename base_type::value_type,
|
||||
class = detail::requires<detail::has_operator_rmul<V>>>
|
||||
class = std::enable_if_t<detail::has_operator_rmul<V>::value>>
|
||||
storage_adaptor& operator*=(double v) {
|
||||
for (auto&& x : *this) x *= v;
|
||||
return *this;
|
||||
|
||||
Reference in New Issue
Block a user