a bundled function as template parameter

I am trying to template 2 function pointers

1
2
3
4
5
6
7
8
9
10
typedef float (*AnimationFunc)( float );

float Linear( float p ){ return p; }
float InverseLinear( float p ){ return p; }


template< AnimationFunc Function, AnimationFunc Inverse >
float getNextPos( float current, float delta, float duration ){
}


Something like this works but the function call feels long

1
2
float next_position = getNextPos< Linear, InverseLinear > ( current_pos, total_speed, accel_time );


It also feels odd that I have to find the name of one inverse function pointer in order for this to work


I tried grouping them inside a struct
1
2
3
4
5
6
7
8
struct Linear {
   static float Function( float p );
   static float Inverse( float p );
};

template< class T >
float getNextPos( float current, float delta, float duration ){
}


But doing this means that I have to have lots of struct for lots of function which I try to avoid


Is there any more pratical approach to this problem ?
Maybe where I only need to declare 1 struct ?
I am trying to template 2 function pointers

[code snipped]

Something like this works but the function call feels long


No it doesn't. It isn't clear exactly what you're trying to accomplish, since your code doesn't make any sense.
If I'm understanding this correctly.... you don't need a template for this.

A template allows you do use a variable type. But you don't have a variable type here... you have a very clearly defined singular type:

typedef float (*AnimationFunc)( float );

So rather than have template parameters... just make these normal parameters and have a non-template function:

1
2
3
4
float getNextPos( AnimationFunc function, AnimationFunc inverse, float current, float delta, float duration )
{
  //...
}
Did I learn wrong that everything that can be defined at compile time should be templated to save run time ?

When I think about it again it doesn't save much or perhaps none in this case

I just need to find a pratical way to group this two function the "function" and it's "inverse" so that I don't need to find it's pair if I want to use one ...



Here is the code if you need to know

1
2
3
4
5
6
7
8
9
10
11
template< Animation::AnimationFunc Function, Animation::AnimationFunc Inverse >
float getNextPosition( float current, float delta, float duration, float dt )
{
	float time = Inverse( current / delta ) * duration + dt;

	if( time < 0.f ) return 0.f;
	if( time >= duration ) return delta;

	return Function( time / duration ) * delta;
}

Last edited on
So you want to relate the two functions just because they differ in the prefix
Maybe use a macro
1
2
3
4
5
6
7
8
#define F_AND_INV( f ) f, Inverse##f

getNextPos( F_AND_INV( Linear ), current_pos, total_speed, accel_time );

//if you fell that's too much, use a wrapper
float getNextPos( AnimationFunction f, float current, float delta, float duration ){
	w_getNextPos( F_AND_INV(f), current, delta, duration );
}


With your structure approach
1
2
3
4
5
6
7
8
struct function{
   typedef float (*f)(float);
   f Direct, Inverse;
};

function Log;
Log.Direct = log;
Log.Inverse = exp;
Last edited on
> everything that can be defined at compile time should be templated to save run time ?

And in case of small functions, inlined too. Some optimizers may baulk at inlining functions that are called via pointers.

You need to define a function and its inverse anyway; why not define them in such a way that:
a. given a function, its inverse can be determined programatically
b. the call can be definitely inlined.

Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<cmath>

template< typename T = float > struct linear
{
    using value_type = T ;

    T operator() ( const T& v ) const { return v ; }

    using inverse = linear<T> ;
};

template< typename T = float > struct quadratic
{
    using value_type = T ;

    T operator() ( const T& v ) const { return v*v ; }

    struct inverse
    {
        T operator() ( const T& v ) const { return std::abs( std::sqrt(v) ) ; }
    };
};


And then:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template< typename FN >
typename FN::value_type getNextPosition( typename FN::value_type current, typename FN::value_type delta,
                                         typename FN::value_type duration, typename FN::value_type dt )
{
	auto time = FN() ( current / delta ) * duration + dt;

	if( time < typename FN::value_type() ) return typename FN::value_type() ;
	if( time >= duration ) return delta;

	return typename FN::inverse() ( time / duration ) * delta;
}

int main( )
{
    auto f = getNextPosition< linear<> >( 1.0f, 0.1f, 0.5f, 3.0f ) ;
    // ...

    auto d = getNextPosition< quadratic<double> >( 1.0, 0.1, 0.5, 3.0 ) ;
    // etc...
}
A function object is a bit confusing (~_~)

1
2
template< typename T >
T quadratic<T>::inverse::operator( const T& v ) const { return std::abs( std::sqrt(v) ) ; }


Writting a definition is quite tough for me
And when there is error it took a while for me to find


and also I just know that I have to perform a little hacks for these templates to prevent linker error

Thanks guys I guess I will go with whatever suited me
Topic archived. No new replies allowed.