template instantiation

Started by
8 comments, last by DevFred 15 years, 10 months ago
I have a function template
template<typename F, typename I, int M, int C>
string qqq(F f)
{
    // ...
}
Now there are only two combinations that make sense for my application:
float, int, 23, 255 and
double, long long, 52, 1023
Is it possible to instantiate the template for only these two combinations, so one can use qqq(float) and qqq(double) without explicitly stating the other three parameters? With class templates one can use typedefs, but I don't know how do to it with function templates.
Advertisement
The simplest solution jumps at me:
string qqq(float f){   return qqq_impl<float,int,23, 255>(f);}string qqq(double d){   return qqq_impl<double, long long, 52, 1023>(f);}

Where qqq_impl could be hidden in a private namespace inside the source file.
There are several possibilities, the easiest being to use overloading instead of templates:
namespace detail {  template<typename F, typename I, int M, int C>  string qqq_impl(F f)  { /* ... */ }}string qqq(float f) { return detail::qqq_impl<float, int, 23, 255>(f); }string qqq(double f) { return detail::qqq_impl<double, long long, 52, 1023>(f); }


EDIT: well, my solution has a detail namespace [rolleyes]
Thanks to both of you!

I came up with another solution involving function pointers. I cannot use overloading with it (the function pointers cannot have the same name as the template function), but that's not so bad.
string (*xxx)(float) = qqq<float, int, 23, 255>;string (*yyy)(double) = qqq<double, long long, 52, 1023>;
The other way is to encapsulate the parameter set.
template<typename F> struct qqq_traits;template<>struct qqq_traits<float>{    typedef float F;    typedef int I;    static const int M = 23;    static const int C = 255;};struct qqq_traits<double>{    typedef double F;    typedef long long I;    static const int M = 52;    static const int C = 1023;};template<typename F>string qqq(F f){    typedef qqq_traits<F> traits;    typedef typename traits::I I;    const int M = traits::M;    const int C = traits::C;    // ...}

This is useful when there are certain sets of classes which should be treated similarly (see, for example, iterator_traits).
Quote:Original post by DevFred
Thanks to both of you!

I came up with another solution involving function pointers. I cannot use overloading with it (the function pointers cannot have the same name as the template function), but that's not so bad.
string (*xxx)(float) = qqq<float, int, 23, 255>;string (*yyy)(double) = qqq<double, long long, 52, 1023>;

The compiler is unable to apply certain optimizations such as inlining here. I wouldn't suggest it.
Thank you Sneftel, that looks very good! ++Rating to all of you.
You don't really need the F typedef inside the struct, right?
Quote:Original post by DevFred
You don't really need the F typedef inside the struct, right?

Depends on the use but, in this case, no.
Not really important for the question, but the double C should be 2047 instead of 1023 (it is used to mask of the exponent, and there are 11 bits for that in a double, not 10).

This topic is closed to new replies.

Advertisement