Is there a way to pass a function template to another function? I tried this but it doesn't work.

template <typename T>
void template_function( T arg ) {
}

void function( template <typename T> void (*func)( T arg ) ) {
}

How can I pass a function template to another function?

Recommended Answers

All 9 Replies

template <typename T> void template_function( T arg ) ;

template <typename T>
void function( void (*func)(T) )
 { /* ... */ }

// this is better, would also accept compatible functions 
// and function objects
template <typename FN>
void better_function( FN arg )
 { /* ... */ }

The first one works if I know what type T is. If I don't, it doesn't work. The second one doesn't work at all. I get an error saying that a type is expected. :(

The first one works if I know what type T is. If I don't, it doesn't work. The second one doesn't work at all.

there was a typo in the second one (corrected now). if we also want to call the function with some arg, here is a modified version of the two functions.

#include <iostream>
#include <cstdlib>
#include <typeinfo>
using namespace std;

template < typename T > void template_function( T arg ) 
 { cout << "template_function< " << typeid(T).name() << " >\n" ; }

template< typename T >struct functor
{
  bool operator() ( const T& arg ) const 
  { return cout << "function_object\n" ; }
};

template < typename T > 
void function( void (*func)(T), T arg ) { func(arg) ; }

template <typename FN, typename T > 
void better_function( FN func, T arg ) { func(arg) ; }

int main()
{
  function( template_function< int >, 23 ) ;
  better_function( template_function< int >, 23 ) ;
  // function( strlen, "hello" ) ; // error
  better_function( strlen, "hello" ) ; // ok
  // function( functor< double >(), 5 ) ; // error
  better_function( functor< double >(), 5 ) ; // ok
}

Okay, I got it to work with your help. But it's still not exactly what I wanted. I still have to know what the type fo Iterator is from main, but that shouldn't be known outside of unit_test. How can I get it so that i can pass bubble_sort to unit_test without knowing that unit_test will sort ints?

/*
  sorting test

  Class based sorting
    by Kimberly Hamrick
*/
#include <algorithm> // for C+'s sort
#include <iostream>  // for C++ I/O
#include <stdlib.h>  // for random numbers

using namespace std;

template <typename Iterator>
void content_display( Iterator first, Iterator last ) {
  while ( first < last )
    cout<< *first++ <<" ";
  cout<<endl;
}

namespace hamrick {
  template <typename Iterator>
  void bubble_sort( Iterator first, const Iterator last ) {
    Iterator current = first;

    // bubble up each element of the array
    while ( current < last ) {
      content_display( first, last );
      bubble_up( last - 1, current );
      ++current;
    }
  }

  template <typename Iterator>
  void bubble_up( Iterator from, const Iterator downto ) {
    // bubble up to the last sorted element
    while ( from > downto ) {
      if ( *from < *(from - 1) ) swap( *from, *(from - 1) );
      --from;
    }
  }
}

// Check that an array of T is sorted
template <typename T>
bool issorted( T array[], const int size ) {
  bool sorted = true;

  // it's sorted if the previous element is smaller
  // than the current element for all elements
  for ( int i = 1; i < size; i++ ) {
    if ( array[i - 1] > array[i] ) {
      sorted = false;
      break;
    }
  }

  return sorted;
}

template <typename FN, typename T >
void better_function( FN func, T arg ) { func(arg) ; }

template <int size, typename FN>
void unit_test( FN func ) {
  int array[size];
  int copy[size];

  // create a random array
  for ( int i = 0; i < size; ++i )
    copy[i] = array[i] = rand();

  // make sure it's sorted
  cout<<"before sort -- "<< boolalpha << issorted( array, size ) <<endl;
  func( array, array + size );
  cout<<"after sort  -- "<< boolalpha << issorted( array, size ) <<endl<<endl;

  // make sure it's sorted the right way
  sort( copy, copy + size );

  for ( int i = 0; i < size; ++i ) {
    if ( array[i] != copy[i] ) {
      cout<<"bad sort!"<<endl;
      break;
    }
  }
}

int main() {
  const int size = 10;

  unit_test<size>( hamrick::bubble_sort<int*> );

  return 0;
}
/*
  sorting test

  Class based sorting
    by Kimberly Hamrick
*/
#include <algorithm> // for C+'s sort
#include <iostream>  // for C++ I/O
#include <stdlib.h>  // for random numbers

using namespace std;

template <typename Iterator>
void content_display( Iterator first, Iterator last ) {
  while ( first /*<*/ != last ) // more flexible
    cout<< *first++ <<" ";
  cout<<endl;
}

namespace hamrick {
  template <typename Iterator>
  void bubble_sort( Iterator first, /*const*/ Iterator last ) {
    Iterator current = first;

    // bubble up each element of the array
    while ( current /*<*/ != last ) {
      content_display( first, last );
      Iterator from = last ;
      bubble_up( /*last - 1*/ --from, current );
      ++current;
    }
  }

  template <typename Iterator>
  void bubble_up( Iterator from,  /*const*/ Iterator downto ) {
    // bubble up to the last sorted element
    while ( from /*>*/ != downto ) {
      Iterator temp = from ;
      if ( *from < *( /*from - 1*/ --temp) )
                swap( *from, */*(from - 1)*/temp );
      --from;
    }
  }
}

// Check that an array of T is sorted
template <typename T>
bool issorted( T array[], const int size ) {
  bool sorted = true;

  // it's sorted if the previous element is smaller
  // than the current element for all elements
  for ( int i = 1; i < size; i++ ) {
    if ( array[i - 1] > array[i] ) {
      sorted = false;
      break;
    }
  }

  return sorted;
}

template <typename FN, typename ITERATOR >
void call_function( FN func, ITERATOR begin, ITERATOR end )
 { func( begin, end ) ; }

template <int size, typename FN>
void unit_test( FN func ) {
  int array[size];
  int copy[size];

  // create a random array
  for ( int i = 0; i < size; ++i )
    copy[i] = array[i] = rand();

  // make sure it's sorted
  cout<<"before sort -- "<< boolalpha << issorted( array, size ) <<endl;
  call_function( func, array, array + size );
  cout<<"after sort  -- "<< boolalpha << issorted( array, size ) <<endl<<endl;

  // make sure it's sorted the right way
  sort( copy, copy + size ); 
  for ( int i = 0; i < size; ++i ) {
    if ( array[i] != copy[i] ) {
      cout<<"bad sort!"<<endl;
      break;
    }
  }
}

int main() {
  const int size = 10;

  unit_test<size>( hamrick::bubble_sort<int*> );

  return 0;
}

note: i have changed some operators on iterators ( < to !=, iter-1 to --iter ) as we do not require random access iterators for a bubble sort. eg. we should be able to do a bubble sort on a std::list<int>

Thanks! But there's still the one problem.

unit_test<size>( hamrick::bubble_sort<int*> );

How does main know that unit_test is going to test sorting ints? What if unit_test tests bubble_sort on five types instead of just one? I want to tell unit_test to use bubble_sort, but let unit_test pick the type.

How does main know that unit_test is going to test sorting ints? What if unit_test tests bubble_sort on five types instead of just one? I want to tell unit_test to use bubble_sort, but let unit_test pick the type.

for that we need to program with types at compile time rather than with variables at run time. this is called template metaprogramming and involves compile-time algorithms, sequences and metafunctions. i would suggest that you leave this problem for the present (until you have mastered things like partial specialization of templates). if you are curious, have a look at http://www.boost.org/libs/mpl/doc/tutorial/tutorial-metafunctions.html
for now; but come back later to tackle such problems.

Okay, thanks for the help! And I'm sorry for making you type so much.

>> ... How does main know that unit_test is going to test sorting ints? What if unit_test tests bubble_sort on five types instead of just one? I want to tell unit_test to use bubble_sort, but let unit_test pick the type.

>>> i would suggest that you leave this problem for the present...

ok, that was some two weeks back. if you have been exploring generic programming during this time, you should be able to figure out the following solution by now.

#include <algorithm> 
#include <iostream>  
#include <cstdlib>  
#include <string>

using namespace std;

template <typename Iterator>
void content_display( Iterator first, Iterator last )
{
  while ( first != last ) 
    cout<< *first++ <<" ";
  cout<<endl;
}

namespace hamrick 
{
  // note: bubble_sort is now a function object 
 // (always preferred over - more flexible than - functioins).
  template <typename Iterator> struct bubble_sort
  {
    // trivial meta function gives the bubble_sort type to be used
    template <typename another_iterator> struct rebind
    { typedef bubble_sort<another_iterator> type ; };
  
    void operator()( Iterator first, Iterator last ) const
    {
      Iterator current = first;
      while ( current != last )
      {
        content_display( first, last );
        Iterator from = last ;
        bubble_up( --from, current );
        ++current;
      }
    }
  
    void bubble_up( Iterator from, Iterator downto ) const 
    {
      while ( from != downto )
      {
        Iterator temp = from ;
        if ( *from < *--temp )
                  swap( *from, *temp );
        --from;
      }
    }
  };
}

template <typename T>
bool issorted( T array[], const int size )
{
  for ( int i = 1; i < size; i++ ) 
    if ( array[i - 1] > array[i] ) return false ;
  return true ;
}

template <typename FN, typename ITERATOR >
void call_function( FN func, ITERATOR begin, ITERATOR end )
{ func( begin, end ) ; }

template <int size, typename FN>
void unit_test( FN func ) 
{
  int array[size];
  int copy[size];

  for ( int i = 0; i < size; ++i )
    copy[i] = array[i] = rand();

  cout<<"before sort -- "<< boolalpha << issorted( array, size ) <<endl;

  // get the right sort_function to sort int arrays
  typedef typename FN::template rebind<int*>::type int_array_sort_fun ;
  call_function( int_array_sort_fun(), array, array + size );
  cout<<"after sort  -- "<< boolalpha << issorted( array, size ) <<endl<<endl;

  sort( copy, copy + size ); 
  for ( int i = 0; i < size; ++i )
    if ( array[i] != copy[i] ) 
    {
      cout<<"bad sort!"<<endl;
      break;
    }
  // get the right sort_function to sort a string
  typedef typename FN::template rebind< string::iterator >::type 
    string_sort_fun ;
  string str = "hello world!" ;
  call_function( string_sort_fun(), str.begin(), str.end() );
  cout << str << '\n' ;
}

int main() {
  const int size = 10;

  // void* is just a place holder; unit_test will rebind as required
  unit_test<size>( hamrick::bubble_sort<void*>() );

  return 0;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.