Skip to content

Commit cfcaa89

Browse files
committed
Use SFINAE
1 parent e880139 commit cfcaa89

1 file changed

Lines changed: 61 additions & 22 deletions

File tree

test/test_dist_helpers.hpp

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <utility>
1212
#include <limits>
1313
#include <stdexcept>
14+
#include <type_traits>
1415
#include <boost/math/tools/precision.hpp>
1516
#include <boost/math/special_functions/next.hpp>
1617
#include <boost/test/unit_test.hpp>
@@ -22,36 +23,74 @@
2223
# define BOOST_CHECK_THROW(x, y)
2324
#endif
2425

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.
2530
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)
2733
{
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)
3635
{
37-
if (c.size() >= 3)
38-
return Dist(c.data()[0], c.data()[1], c.data()[2]);
36+
return Dist(c.data()[0]);
3937
}
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)
4155
{
42-
if (c.size() >= 2)
43-
return Dist(c.data()[0], c.data()[1]);
56+
return Dist(c.data()[0], c.data()[1]);
4457
}
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)
4675
{
47-
if (c.size() >= 1)
48-
return Dist(c.data()[0]);
76+
return Dist(c.data()[0], c.data()[1], c.data()[2]);
4977
}
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);
5594
}
5695

5796
template <class Dist, class V>

0 commit comments

Comments
 (0)