little help playing with concept and templates

I have this toy that is trying to conditionally inherit different base classes to change the behavior of get value. That may not be the best plan here anyway(open to ideas other than specialization) but no matter what I do, getvalue is either 'not a member of' or 'does not depend on template parameter' errors appear depending on whether I try to call this->getvalue or without 'this'. I even tried a fake depend on template parameter (the *(T)1 ) but it didn't solve it.

I am sure its something simple... but what am I doing wrong?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
template <typename T> 
   concept numericalConstraint = std::integral<T> || std::floating_point<T>;
   
//inherit one of these two based off the types of T
template <typename T> struct randomRealBase
{
   std::uniform_real_distribution<T> realDistribution;   
   T getValue(std::default_random_engine & generator){return realDistribution(generator)*(T)1;}
};   

template <typename T> struct randomIntBase
{
   std::uniform_int_distribution<T> intDistribution; 
   T getValue(std::default_random_engine & generator){return intDistribution(generator)*(T)1;}

template <typename T> requires numericalConstraint<T>
class randomGenerator_t : std::conditional<std::integral<T>, randomIntBase<T>, randomRealBase<T> >
{
   public:
   operator T() 
   {	   
        return this->getValue(generator);
   }
};   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <concepts>
#include <random>
#include <limits>

namespace detail
{
    template < typename T > struct distribution ;
    template < std::integral T > struct distribution<T> { using type = std::uniform_int_distribution<T> ; };
    template < std::floating_point T > struct distribution<T> { using type = std::uniform_real_distribution<T> ; };
}

template < typename T > requires std::integral<T> || std::floating_point<T>
T uniform_random( T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max() )
{
    static std::mt19937 rng( std::random_device{}() ) ;
    static typename detail::distribution<T>::type distribution ;
    using param_type = typename decltype(distribution)::param_type ;

    distribution.param( param_type(min,max) ) ;
    return distribution(rng) ;
}

int main()
{
    for( int i = 0 ; i < 10 ; ++i ) std::cout << uniform_random/*<int>*/( 10, 99 ) << ' ' ;
    std::cout << '\n' ;

    for( int i = 0 ; i < 10 ; ++i ) std::cout << uniform_random<double>( 10, 99 ) << ' ' ;
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/4490934a8a745c89
There's a typo in line 17 in the OP:

 
class randomGenerator_t : std::conditional<std::integral<T>, randomIntBase<T>, randomRealBase<T> >
Should be
 
class randomGenerator_t : std::conditional_t<std::integral<T>, randomIntBase<T>, randomRealBase<T> >
or
 
class randomGenerator_t : typename std::conditional<std::integral<T>, randomIntBase<T>, randomRealBase<T> >::type

Last edited on
Thank you both!
Mbozzi, is one of those 2 forms preferred? I like the first one... seems cleaner..?
Last edited on
I don't know of any reasons to use #2 over #1. So use #1 probably.
thx again!
Topic archived. No new replies allowed.