|
11 | 11 | #include <utility> |
12 | 12 | #include <limits> |
13 | 13 | #include <stdexcept> |
| 14 | +#include <type_traits> |
14 | 15 | #include <boost/math/tools/precision.hpp> |
15 | 16 | #include <boost/math/special_functions/next.hpp> |
16 | 17 | #include <boost/test/unit_test.hpp> |
|
22 | 23 | # define BOOST_CHECK_THROW(x, y) |
23 | 24 | #endif |
24 | 25 |
|
| 26 | +namespace test_dist_helpers_detail { |
| 27 | + |
| 28 | +// Construct Dist from a single parameter when it has a one-argument |
| 29 | +// constructor; otherwise there is nothing lower to try, so throw. |
25 | 30 | template <class Dist, class Container> |
26 | | -Dist make_distribution(const Container& c) |
| 31 | +typename std::enable_if<std::is_constructible<Dist, typename Dist::value_type>::value, Dist>::type |
| 32 | +construct_distribution_1(const Container& c) |
27 | 33 | { |
28 | | - using value_type = typename Dist::value_type; |
29 | | - |
30 | | - #ifdef _MSC_VER |
31 | | - #pragma warning(push) |
32 | | - #pragma warning(disable:4127) // conditional expression is constant |
33 | | - #endif |
34 | | - |
35 | | - if (std::is_constructible<Dist, value_type, value_type, value_type>::value) |
| 34 | + if (c.size() >= 1) |
36 | 35 | { |
37 | | - if (c.size() >= 3) |
38 | | - return Dist(c.data()[0], c.data()[1], c.data()[2]); |
| 36 | + return Dist(c.data()[0]); |
39 | 37 | } |
40 | | - if (std::is_constructible<Dist, value_type, value_type>::value) |
| 38 | + throw std::domain_error("Object not initialized!"); |
| 39 | +} |
| 40 | + |
| 41 | +template <class Dist, class Container> |
| 42 | +typename std::enable_if<!std::is_constructible<Dist, typename Dist::value_type>::value, Dist>::type |
| 43 | +construct_distribution_1(const Container&) |
| 44 | +{ |
| 45 | + throw std::domain_error("Object not initialized!"); |
| 46 | +} |
| 47 | + |
| 48 | +// Construct Dist from two parameters when it has a two-argument constructor |
| 49 | +// and enough data is present; otherwise fall back to the one-argument form. |
| 50 | +template <class Dist, class Container> |
| 51 | +typename std::enable_if<std::is_constructible<Dist, typename Dist::value_type, typename Dist::value_type>::value, Dist>::type |
| 52 | +construct_distribution_2(const Container& c) |
| 53 | +{ |
| 54 | + if (c.size() >= 2) |
41 | 55 | { |
42 | | - if (c.size() >= 2) |
43 | | - return Dist(c.data()[0], c.data()[1]); |
| 56 | + return Dist(c.data()[0], c.data()[1]); |
44 | 57 | } |
45 | | - if (std::is_constructible<Dist, value_type>::value) |
| 58 | + return construct_distribution_1<Dist>(c); |
| 59 | +} |
| 60 | + |
| 61 | +template <class Dist, class Container> |
| 62 | +typename std::enable_if<!std::is_constructible<Dist, typename Dist::value_type, typename Dist::value_type>::value, Dist>::type |
| 63 | +construct_distribution_2(const Container& c) |
| 64 | +{ |
| 65 | + return construct_distribution_1<Dist>(c); |
| 66 | +} |
| 67 | + |
| 68 | +// Construct Dist from three parameters when it has a three-argument |
| 69 | +// constructor and enough data is present; otherwise fall back to two. |
| 70 | +template <class Dist, class Container> |
| 71 | +typename std::enable_if<std::is_constructible<Dist, typename Dist::value_type, typename Dist::value_type, typename Dist::value_type>::value, Dist>::type |
| 72 | +construct_distribution_3(const Container& c) |
| 73 | +{ |
| 74 | + if (c.size() >= 3) |
46 | 75 | { |
47 | | - if (c.size() >= 1) |
48 | | - return Dist(c.data()[0]); |
| 76 | + return Dist(c.data()[0], c.data()[1], c.data()[2]); |
49 | 77 | } |
50 | | - #ifdef _MSC_VER |
51 | | - #pragma warning(pop) |
52 | | - #endif |
53 | | - |
54 | | - throw std::domain_error("Object not initialized!"); |
| 78 | + return construct_distribution_2<Dist>(c); |
| 79 | +} |
| 80 | + |
| 81 | +template <class Dist, class Container> |
| 82 | +typename std::enable_if<!std::is_constructible<Dist, typename Dist::value_type, typename Dist::value_type, typename Dist::value_type>::value, Dist>::type |
| 83 | +construct_distribution_3(const Container& c) |
| 84 | +{ |
| 85 | + return construct_distribution_2<Dist>(c); |
| 86 | +} |
| 87 | + |
| 88 | +} // namespace test_dist_helpers_detail |
| 89 | + |
| 90 | +template <class Dist, class Container> |
| 91 | +Dist make_distribution(const Container& c) |
| 92 | +{ |
| 93 | + return test_dist_helpers_detail::construct_distribution_3<Dist>(c); |
55 | 94 | } |
56 | 95 |
|
57 | 96 | template <class Dist, class V> |
|
0 commit comments