2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00

Fix and implement test using C++20 ranges

This commit is contained in:
Matt Borland
2021-03-15 22:39:20 +03:00
parent 98dcc682a9
commit 5d6ebd738d
2 changed files with 40 additions and 4 deletions

View File

@@ -274,12 +274,33 @@ class hyperexponential_distribution
PolicyT());
}
private: template <typename T>
class is_iterator
{
private:
using yes = char;
struct no { char x[2]; };
// Iterators only require pre-increment and dereference operator (24.2.2)
template <typename U, typename = decltype(*std::declval<U&>(), void(), ++std::declval<U&>(), void())>
static yes test(const U&&);
template <typename U>
static no test(...);
public:
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char));
};
// Two arg constructor from 2 ranges, we SFINAE this out of existence if
// either argument type is incrementable as in that case the type is
// probably an iterator:
public: template <typename ProbRangeT, typename RateRangeT,
typename std::enable_if<!std::is_pointer<ProbRangeT>::value &&
!std::is_pointer<RateRangeT>::value, bool>::type = true>
typename std::enable_if<!is_iterator<ProbRangeT>::value &&
!is_iterator<RateRangeT>::value, bool>::type = true>
hyperexponential_distribution(ProbRangeT const& prob_range,
RateRangeT const& rate_range)
: probs_(std::begin(prob_range), std::end(prob_range)),
@@ -300,8 +321,8 @@ class hyperexponential_distribution
// Note that we allow different argument types here to allow for
// construction from an array plus a pointer into that array.
public: template <typename RateIterT, typename RateIterT2,
typename std::enable_if<std::is_pointer<RateIterT>::value ||
std::is_pointer<RateIterT2>::value, bool>::type = true>
typename std::enable_if<is_iterator<RateIterT>::value ||
is_iterator<RateIterT2>::value, bool>::type = true>
hyperexponential_distribution(RateIterT const& rate_first,
RateIterT2 const& rate_last)
: probs_(std::distance(rate_first, rate_last), 1), // will be normalized below

View File

@@ -386,4 +386,19 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(error_cases, RealT, test_types)
BOOST_MATH_CHECK_THROW(dist_t(probs2, rates), std::domain_error);
BOOST_MATH_CHECK_THROW(dist_t(probs.begin(), probs.begin(), rates.begin(), rates.begin()), std::domain_error);
BOOST_MATH_CHECK_THROW(dist_t(rates.begin(), rates.begin()), std::domain_error);
// Test C++20 ranges
#if (__cplusplus > 202000L || _MSVC_LANG > 202000L) && defined(__cpp_lib_ranges)
#include <ranges>
#include <array>
std::array<RealT, 2> probs_array {1,2};
std::array<RealT, 3> rates_array {1,2,3};
BOOST_MATH_CHECK_THROW(dist_t(std::ranges::begin(probs_array), std::ranges::end(probs_array), std::ranges::begin(rates_array), std::ranges::end(rates_array)), std::domain_error);
const auto probs_range = probs_array | std::views::all;
const auto rates_range = rates_array | std::views::all;
BOOST_MATH_CHECK_THROW(dist_t(probs_range, rates_range), std::domain_error);
#endif
}