little help playing with concept and templates

Apr 14, 2023 at 5:39pm
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);
   }
};   
Apr 14, 2023 at 6:07pm
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
Apr 14, 2023 at 6:14pm
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 Apr 14, 2023 at 6:15pm
Apr 14, 2023 at 6:19pm
Thank you both!
Mbozzi, is one of those 2 forms preferred? I like the first one... seems cleaner..?
Last edited on Apr 14, 2023 at 6:21pm
Apr 14, 2023 at 6:27pm
I don't know of any reasons to use #2 over #1. So use #1 probably.
Apr 14, 2023 at 6:28pm
thx again!
Topic archived. No new replies allowed.