dependent template parameter?

Discussion in 'C++' started by stephen.diverdi@gmail.com, Sep 24, 2009.

  1. Guest

    Any suggestions on how to accomplish something like this doScale
    function?

    #include <stdio.h>

    template < typename T, T scale >
    T doScale ( const T &x )
    {
    return ( x * scale );
    }

    int main ()
    {
    float x = 1;
    float y = doScale< float, 2.0f >( x );
    printf( "%f %f\n", x, y );

    int a = 1;
    int b = doScale< int, 3 >( a );
    printf( "%d %d\n", a, b );

    return 0;
    }

    I want to have the second template parameter be a constant of a type
    that is determined by the first template parameter. g++ and comeau
    both reject it. If you're curious, I'm looking to replace a run-time
    constant with a compile-time constant in some critical code. Thanks,

    -stephen diverdi
     
    , Sep 24, 2009
    #1
    1. Advertising

  2. wrote:
    > Any suggestions on how to accomplish something like this doScale
    > function?
    >
    > #include <stdio.h>
    >
    > template < typename T, T scale >
    > T doScale ( const T &x )
    > {
    > return ( x * scale );
    > }
    >
    > int main ()
    > {
    > float x = 1;
    > float y = doScale< float, 2.0f >( x );
    > printf( "%f %f\n", x, y );
    >
    > int a = 1;
    > int b = doScale< int, 3 >( a );
    > printf( "%d %d\n", a, b );
    >
    > return 0;
    > }
    >
    > I want to have the second template parameter be a constant of a type
    > that is determined by the first template parameter. g++ and comeau
    > both reject it. If you're curious, I'm looking to replace a run-time
    > constant with a compile-time constant in some critical code. Thanks,


    You can't have 'float' as the type of the non-type template argument.
    You're SOL in this matter. Pass the scale by value. The compiler will
    optimize it for you.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 24, 2009
    #2
    1. Advertising

  3. sdiverdi Guest

    >
    > You can't have 'float' as the type of the non-type template argument.
    > You're SOL in this matter.  Pass the scale by value.  The compiler will
    > optimize it for you.
    >

    Hmm, too bad. Thanks!

    -stephen diverdi
     
    sdiverdi, Sep 25, 2009
    #3
  4. dix75 Guest

    On Sep 25, 5:38 am, sdiverdi <> wrote:
    > > You can't have 'float' as the type of the non-type template argument.
    > > You're SOL in this matter.  Pass the scale by value.  The compiler will
    > > optimize it for you.

    >
    > Hmm, too bad.  Thanks!
    >
    > -stephen diverdi
    >


    Try so

    template < typename T>
    T doScale ( const T &x, double scale)
    {
    return ( x * scale );

    }

    int main ()
    {
    float x = 1;
    float y = doScale( x, 2.0f );
    printf( "%f %f\n", x, y );

    int a = 1;
    int b = doScale( a, 3 );
    printf( "%d %d\n", a, b );

    return 0;

    }
     
    dix75, Sep 25, 2009
    #4
  5. dix75 Guest

    On Sep 25, 5:38 am, sdiverdi <> wrote:
    > > You can't have 'float' as the type of the non-type template argument.
    > > You're SOL in this matter.  Pass the scale by value.  The compiler will
    > > optimize it for you.

    >
    > Hmm, too bad.  Thanks!
    >
    > -stephen diverdi
    >


    Try so


    template < typename T>
    T doScale ( const T &x, double scale)
    {
    return ( x * scale );

    }

    int main ()
    {
    float x = 1;
    float y = doScale( x, 2.0f );
    printf( "%f %f\n", x, y );

    int a = 1;
    int b = doScale( a, 3 );
    printf( "%d %d\n", a, b );

    return 0;

    }
     
    dix75, Sep 25, 2009
    #5
  6. Scooser Guest

    Hi Stephen,
    I'm not sure if this helps you, but as far as I understand you, your
    idea ist to replace a "float y = CONST_XYZ * x;" with something like
    this "float y = doScale<float, CONST_XYZ>(x)". Hoping that the
    compiler can do better with the template right?

    This is possible but to make it work you have to add a layer of
    template indirection. For example you can do it like this

    #include <stdio.h>

    namespace Constant
    {
    enum const_id
    {
    ONE,
    TWO
    };

    namespace {

    template<typename T, const_id id> class CScaler;
    template<>
    struct CScaler<float, ONE>
    {
    float operator () (const float& value) const
    { return 2.0f * value; }
    };

    template<>
    struct CScaler<int, TWO>
    {
    int operator () (const int& value) const
    { return 3 * value; }
    };
    }

    template<const_id id, typename T>
    inline T scale (const T& value)
    {
    CScaler<T,id> scaler;
    return scaler(value);
    }
    }

    int main(void)
    {
    printf ("Test");

    float x = 1.0f;
    float y = Constant::scale<Constant::ONE>( x );
    printf( "%f %f\n", x, y );

    int a = 1;
    int b = Constant::scale<Constant::TWO>( a );
    printf( "%d %d\n", a, b );

    return 0;
    }


    But in general I don't see the benefit because the compiler should be
    able to optimize the "runtime" constants away as long as they are
    known on compile time which is required to make the template approach
    work.
     
    Scooser, Sep 25, 2009
    #6
  7. Noah Roberts Guest

    In article <7cafa50b-51be-46de-a979-95bc2d022311
    @m3g2000pri.googlegroups.com>, says...
    >
    > >
    > > You can't have 'float' as the type of the non-type template argument.
    > > You're SOL in this matter.  Pass the scale by value.  The compiler will
    > > optimize it for you.
    > >

    > Hmm, too bad. Thanks!


    There is, however, an alternative.

    If you look in the boost::units library you'll find a "static_rational"
    class. It is meant to address this problem for you and is mostly
    algebraicly complete (there are some impossible operators that were not
    implemented). Or you can implement your own fairly easily if you don't
    need all that:

    template < int Num, int Denom >
    struct rational
    {
    static double value() { return static_cast<double>(Num)/Denom; }
    };

    Now your code:

    template < typename T, typename Scale >
    T doScale(T const& x)
    {
    return static_cast<T>(x * Scale::value());
    }
     
    Noah Roberts, Sep 25, 2009
    #7
  8. sdiverdi Guest

    On Sep 25, 12:30 am, dix75 <> wrote:
    >
    > Try so
    >
    > template < typename T>
    > T doScale ( const T &x, double scale)
    > {
    >         return ( x * scale );
    >
    > }
    >
    > int main ()
    > {
    >         float x = 1;
    >         float y = doScale( x, 2.0f );
    >         printf( "%f %f\n", x, y );
    >
    >         int a = 1;
    >         int b = doScale( a, 3 );
    >         printf( "%d %d\n", a, b );
    >
    >         return 0;
    >
    > }


    Ah, thanks but that's what I have already. I was hoping to avoid the
    run-time variable for scale, as I always pass a compile-time constant
    in there, in the interest of trying to optimize an inner loop.

    -stephen diverdi
     
    sdiverdi, Sep 29, 2009
    #8
  9. sdiverdi Guest

    On Sep 25, 1:34 am, Scooser <> wrote:
    >     template<typename T, const_id id> class CScaler;
    >     template<>
    >     struct CScaler<float, ONE>
    >     {
    >       float operator () (const float& value) const
    >       { return 2.0f * value; }
    >     };
    >
    >     template<>
    >     struct CScaler<int, TWO>
    >     {
    >       int operator () (const int& value) const
    >       { return 3 * value; }
    >     };


    Interesting idea, but since this will require multiple complete
    implementations of the doScale function, each with the different
    compile-time constants hard-wired in, it doesn't gain me anything over
    just writing multiple functions.

    > But in general I don't see the benefit because the compiler should be
    > able to optimize the "runtime" constants away as long as they are
    > known on compile time which is required to make the template approach
    > work.


    It should, but what I have is a large-ish function that uses some
    constants that differ for char vs. short vs. float versions for some
    heavy calculations. Looking at the assembly, I can see that a
    variable is getting passed around, rather than a constant. So I was
    looking for a way to force the compiler's hand.

    Thanks,

    -stephen diverdi
     
    sdiverdi, Sep 29, 2009
    #9
  10. sdiverdi Guest

    On Sep 25, 10:59 am, Noah Roberts <> wrote:
    >
    > template < int Num, int Denom >
    > struct rational
    > {
    >   static double value() { return static_cast<double>(Num)/Denom; }
    >
    > };


    Ah, of course! I guess my template-fu is still a bit weak, as these
    (ab)uses of the type system often don't occur to me. I'll give it a
    try and see what the compiler can do with it. Thanks!

    -stephen diverdi
     
    sdiverdi, Sep 29, 2009
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Nate Barney

    dependent template parameter

    Nate Barney, Sep 15, 2006, in forum: C++
    Replies:
    2
    Views:
    360
    Nate Barney
    Sep 15, 2006
  2. er
    Replies:
    1
    Views:
    343
  3. Stuart Redmann
    Replies:
    5
    Views:
    482
    Stuart Redmann
    Dec 14, 2007
  4. puzzlecracker
    Replies:
    1
    Views:
    523
    James Kanze
    Aug 7, 2008
  5. Isti
    Replies:
    2
    Views:
    726
Loading...

Share This Page