I'm writing a function which I want to accept a distribution as a parameter. Let's say the following:
#include<random>
#include<iostream>
using namespace std;
random_device rd;
mt19937 gen(rd());
void print_random(uniform_real_distribution<>& d) {
cout << d(gen);
}
Now is there a way to generalise this code, in a short way, in C++ such that it would accept all distributions and distributions only (otherwise the compiler should complain)? Edit: To clarify, the solution should also be able to accept only a subset of all distributions (which would have to be pre-specified).
I would for example accept the ability to define a type as a collection of allowed types but it would be even better if there is already a type which has this property for distributions.
The symbol "⊆" means "is a subset of". The symbol "⊂" means "is a proper subset of". Since all of the members of set A are members of set D, A is a subset of D.
In set theory, a subset is denoted by the symbol ⊆ and read as 'is a subset of'. Using this symbol we can express subsets as follows: A ⊆ B; which means Set A is a subset of Set B. Note: A subset can be equal to the set.
In the strict mathematical sense, C isn't a subset of C++. There are programs that are valid C but not valid C++ and even a few ways of writing code that has a different meaning in C and C++. However, C++ supports every programming technique supported by C95 (C90 plus an Amendment) and earlier.
To subset lists we can utilize the single bracket [ ] , double brackets [[ ]] , and dollar sign $ operators. Each approach provides a specific purpose and can be combined in different ways to achieve the following subsetting objectives: Subset list and preserve output as a list.
There is no such traits in standard library. You can just write something like
template<typename T>
struct is_distribution : public std::false_type {};
and specialize for each type, that is distribution
template<typename T>
struct is_distribution<std::uniform_int_distribution<T> > :
public std::true_type {};
Then just
template<typename Distr>
typename std::enable_if<is_distribution<Distr>::value>::type
print_random(Distr& d)
{
cout << d(gen);
}
Also, you can use something like concepts-lite (but with decltypes, since there is no this feature now), it can not work in some cases. In standard there are rules, that should any distribution follow (n3376 26.5.1.6/Table 118).
template<typename D>
constexpr auto is_distribution(D& d) ->
decltype(std::declval<typename D::result_type>(),
std::declval<typename D::param_type>(),
d.reset(), d.param(), d.param(std::declval<typename D::param_type>()), true);
template<typename D>
auto print_random(D& d) -> decltype(is_distribution(d), void())
{
}
If you want just check that type is callable with some generator and execution of this call returns result_type you can just simplify function
template<typename D>
auto is_distribution(D& d) ->
decltype(std::is_same<typename D::result_type,
decltype(d(*static_cast<std::mt19937*>(0)))>::value);
all this things will be much simple, when concepts-lite will be available in standard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With