2
\$\begingroup\$

Previous question:

Generate a random numbers class

I have come up with three different ways to define type of mUniformDistribution. All of them work fine in VC++ 2013 and GCC.

First approach by SFINAE:

template<typename U >
static typename std::enable_if<
    std::is_integral<U>::value, 
    std::uniform_int_distribution<U>
>::type dist(); 

template<typename U >
static typename std::enable_if<
    std::is_floating_point<U>::value,
    std::uniform_real_distribution<U>
>::type dist();

decltype(dist<T>()) mUniformDistribution;

Second approach by SFINAE:

template<typename U, typename std::enable_if<std::is_integral<U>::value>::type* = nullptr>
static auto dist() -> std::uniform_int_distribution<U>;

template<typename U, typename std::enable_if<std::is_floating_point<U>::value>::type* = nullptr>
static auto dist() -> std::uniform_rea_distribution<U>;

decltype(dist<T>()) mUniformDistribution;

Third approach:

I'm quite comfortable with it for simplicity.

template <typename T>
using dist = typename std::conditional<
    std::is_integral<T>::value,
    std::uniform_int_distribution<T>,
    std::uniform_real_distribution<T>>::type;

dist<T> mUniformDistribution;

which one is the better approach and why?

Code sample:

#include <random>
#include <iostream>
#include <type_traits>


template<typename T >
class Random
{
public:
    Random(const T& min, const T& max)
        : mUniformDistribution(min, max)
    {}

    T operator()()
    {
        return mUniformDistribution(mEngine);
    }

private:
    std::default_random_engine mEngine{ std::random_device()() };
    /////////////////////////////////////////
    // first approach
    // 
    //template<typename U >
    //static typename std::enable_if<
    //  std::is_integral<U>::value,
    //  std::uniform_int_distribution<U>
    //>::type dist(); 
    //
    //template<typename U >
    //static typename std::enable_if<
    //  std::is_floating_point<U>::value,
    //  std::uniform_real_distribution<U>
    //>::type dist();
    //decltype(dist<T>()) mUniformDistribution;

    //////////////////////////////////////////
    // second approach
    //
    //template<typename U, typename std::enable_if<std::is_integral<U>::value>::type* = nullptr>
    //static auto   dist() -> std::uniform_int_distribution<U>;
    //
    //template<typename U, typename std::enable_if<std::is_floating_point<U>::value>::type* = nullptr>
    //static auto   dist() -> std::uniform_real_distribution<U>;
    //decltype(dist<T>()) mUniformDistribution;

    //////////////////////////////////////////
    // third approach
    //
    template <typename U>
    using dist = typename std::conditional<
        std::is_integral<U>::value,
        std::uniform_int_distribution<U>,
        std::uniform_real_distribution<U>>::type;

    dist<T> mUniformDistribution;
};

int main()
{
    Random<int> getRandom(0, 9);
    for (int i = 0; i<9; ++i)
        std::cout << getRandom() << '\n';
}
\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.