function as template arguments

Hello,

I have a function that calls intensively an other function. But I need to be able to change this latest function to test different configurations.

I'm trying something like :
1
2
3
4
5
6
7
template < double _distance(vect& v1, vect& v2) >
void dosomething{
...
dist = _distance(v1,v2);
...

};


what happen at compilation time and what kind of performance can I excpect comparing to a hard coded distance function ?

Thanks by advance

AlexisM
That doesn't make much sense.

Do you mean something like:

1
2
3
4
5
template< typename Fn >
void do_something( Fn f, vect& v1, vect& v2 )
{
    f( v1, fv );
}


?
Hi, Alexis:

That'll never work. Template arguments are restricted to types and classes. You can, however, use function objects for what you have in mind.

1
2
3
4
5
6
7
struct _distance1 {
  double operator() (vect& v1, vect& v2) {... return delta;}
} _distance1;

struct _distance2 {
  double operator() (vect& v1, vect& v2) {... return delta;}
} _distance2;


Practically speaking, you'll probably want to actually define the functions in another file, but once they're defined, you should be able to do this (and make sure to do it in a header file)...

1
2
3
4
5
inline template <class T> do_something {
...
double d = T (v1, v2) ;
...
}


Now you should be able to call

1
2
3
4
...
do_something <_distance1> () ;
do_something <_distance2> () ;
...


and call the different functions that way.

Of course, I have absolutely no freaking idea if that will work or not, but it sure looks good from here. :)
Last edited on
You can also use pointers to function
LOL I was just gonna delete that whole last post, Bazzy, because I finally got overwhelmed with curiosity and it just doesn't work that way. What will work follows...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// switcher.h

#include <cstdlib>
#include <iostream>

using namespace std ;

struct _distance1 {
  double operator() (int i1, int i2) {return 1.1111;}
} ;

struct _distance2 {
  double operator() (int i1, int i2) {return 2.2222;}
} ;

template <class T>
inline double do_something (T t, int i1, int i2) {
return t (i1, i2) ;
}


and then...

1
2
3
4
5
6
7
8
9
10
11
12
13
// main.cpp

#include "switcher.h"

int main(int argc, char *argv[])
{
    _distance1 d1 ;
    _distance2 d2 ;
    int i1 = 1 ;
    int i2 = 2 ;
    cout << do_something (d2, i1, i2) ;
    return EXIT_SUCCESS;
}


where in the call to do_something() you switch the first parameter to d1 or d2, depending on which "function" you want to use.

(I used ints instead of vects (whatever they are exactly) just to make life simpler, but the same principle should apply.)

You're extremely correct about function pointers being a more obvious solution, though. For all practical purposes there's no real difference between using them and the solution above except for the word "template."
For those of you who might not know, this is how a function pointer works:

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
// main.cpp

#include <iostream>

using namespace std;

void hello (void)
{
     cout << "Hello, World!" ;
}

void (*hi) (void) ;

int main(int argc, char *argv[])
{
    try
    {
        hi = &hello ;
        hi() ;
        return 0;
    }
    catch (exception e)
    {
        cout << "STOP!" << e.what() << endl ;
    }
}
Hi ,

I'm a bit confused, because it does work.

The following code compiles and run :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string>

using namespace std;

inline void print(std::string message){cout<<message<<endl;}

template < void _print_func(std::string message) > 
inline void use_print(std::string message){
    _print_func(message);
}

int main(){
    use_print<print>("Coucou!");
}


I tried this way because, I had noticed that the use of pointer to functions was terrible for execution time. So I wanted to know, as it uses templates, if the resulting binary was equivalent to the hard coded version :

1
2
3
int main(){
    cout<"Coucou!"<<endl;
}


Thanks
Last edited on
Of course the above works.

1
2
3
template< int x >
void print_x() 
{  cout << x; }


works, and the above is essentially the same thing except the type is not int, but rather a function pointer.

Not sure if the above is better than a function pointer. The question is: can the compiler inline the function (print, that is)?

In my original reply, the design paradigm I used is used throughout the STL and in general can benefit from inlining if Fn is a function object whose operator() is inlined in a header file.

Wow. That does work. That's a really cool trick, Alexis. Wow. That's the coolest trick I think I've ever seen.

The binaries aren't exactly equivalent. The executable for your template version is a whole 25 KB larger than the .exe for your plain old cout version. It probably executes just a little bit slower for the extra function call, but preprocesssing and compiling takes away all the template stuff and just leaves the functions that are the result.
Is there a way to ask g++ to say if has inlined the function ?

Never have used g++. Rarely read any compiler output past the "Done" or "Couldn't Be Done" parts either. Using the word "inline" is supposed to guarantee that a function gets inlined, though, so you really shouldn't need to ask. From what I understand compilers and optimizers often inline functions without being told to as well just because that's their job.
No, using the keyword inline only asks the compiler to inline it if possible. The compiler is not forced to do it.

Load a debug version of your executable into gdb and ask it to print out the address of the function.

Topic archived. No new replies allowed.