One template specialization for multiple types

Dec 25, 2014 at 10:21pm
I want to make a template function that works different for int types and different for floating types. I don't want to write specializations for float, double and long double separately. I'd like to write one specialization that works for every floating type. It can't be checked in function using type_traits. How to do it?

My function:
1
2
template <typename Arg>
Arg RandomNum(const Arg n);
Last edited on Dec 25, 2014 at 10:23pm
Dec 25, 2014 at 10:56pm
It can't be checked in function using type_traits
Why?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <typename Arg>
typename std::enable_if<std::is_floating_point<Arg>::value, Arg>::type 
RandomNum(const Arg n)
{
    std::cout << "Floating point!";
    return n;
}

template <typename Arg>
typename std::enable_if<std::is_integral<Arg>::value, Arg>::type 
RandomNum(const Arg n)
{
    std::cout << "Integer!";
    return n;
}
Dec 25, 2014 at 11:11pm
I thought about checking in if statement inside the function, that wouldn't work 'cuz my function creates std::uniform distibutions (int or real). I didn't even know about the way you provided. Thank you for your help, second time :).
Dec 25, 2014 at 11:24pm
You can use it inside function too:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template<typename Arg>
Arg RandomNum_impl(const Arg n, std::true_type)
{
    std::cout << "Floating point!";
    return n;
}

template<typename Arg>
Arg RandomNum_impl(const Arg n, std::false_type)
{
    std::cout << "Int!";
    return n;
}

template <typename Arg>
Arg RandomNum(const Arg n)
{
    return RandomNum_impl(n, std::is_floating_point<Arg>{});
}
Furst approach is called SFINAE, second — tag dispatch
Dec 26, 2014 at 11:32am
I meant I couldn't do something like this:

1
2
3
4
5
6
if (std::is_floating_point<Arg>::value){
std::uniform_real_distriburion<Arg> dis(0, n);
return dis(engine);
}
std::uniform_int_distribution<Arg> dis(0, n);
return dis(engine);


It would check what's the type of passed argument, and even if it was int, which wouldn't activate if statement, it would post wrong type passed to std::unform_real_distribution error.
Last edited on Dec 26, 2014 at 12:02pm
Dec 26, 2014 at 3:18pm
> I meant I couldn't do something like this:
> It would check what's the type of passed argument, and even if it was int,
> which wouldn't activate if statement, it would post wrong type passed ...

You can, if you are desperate; use compile-time optioning instead of run-time optioning.

Though I'm not sure that uniform distribution [0,n] for integer and normal distribution (0,n) for floating point would form an intuitive interface.

1
2
3
4
5
6
7
8
9
10
template < typename T >
typename std::enable_if< std::is_arithmetic<T>::value, T >::type random( const T& n )
{
    static std::mt19937 engine{ /* seed (seq) */ } ;
    using distribution = typename std::conditional< std::is_integral<T>::value,
                                                    std::uniform_int_distribution<T>,
                                                    std::normal_distribution<T> >::type ;
    distribution dis{ T{}, n } ;
    return dis(engine) ;
}

http://coliru.stacked-crooked.com/a/b4a2071fd7290a54
Dec 26, 2014 at 5:15pm
Thanks. I'm going to learn a lot about C++ from this forum. Again I didn't know about this possibility. I still need to read like 600 pages of my book, so I hope that sometime I'll know C++ as good as you guys.
Dec 26, 2014 at 5:54pm
One advice, as you do not seems to be an absolute beginner. Get some standard library reference, for example http://en.cppreference.com/w/ , and look what standard library has to offer. No book will cover whole library, and it would be a letdown to spend several days implementing, say, class for complex arithmetic and then learning about <complex>.

For example, I doubt that your book covers this little helper: http://en.cppreference.com/w/cpp/utility/rel_ops/operator_cmp
Dec 26, 2014 at 6:19pm
Yeah, I'm not "an absolute beginner", so far I read 600 pages of S. Prata's book (it's not "C++ primer plus", probably you don't know it 'cuz I think it's only in Polish language (strange, right?)). Thanks for your advice, I'll do to it. And you're right one another time, I didn't know about those template operator functions. So now I need to read:
- standard library reference
- WinApi reference
- some graphics library reference (for games)
EDIT
I was mistaken, it is primer plus
Last edited on Dec 28, 2014 at 11:59pm
Topic archived. No new replies allowed.