Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get template template argument deduction working with functions?

Tags:

c++

templates

Consider a set of functions like

template< class Fun >
void A( const Fun& )
{
}

template< class Fun >
void B( const Fun& )
{
}

template< class Fun >
void C( const Fun& )
{
}

designed to take function types as arguments. Then, this is perfectly ok:

template< class T >
void Func( const T& )
{
}

A( Func< int > );
B( Func< int > );
C( Func< int > );

Now I wanted to get rid of repeating the int temaplate argument so I tried this:

template< class T >
struct Helper
{
  template< template< class > class Fun >
  static void A( Fun< T >& f )
  {
    A( f );
  }

  template< template< class > class Fun >
  static void B( Fun< T >& f )
  {
    B( f );
  }

  ...
};

typedef Helper< int > IntHelper;
IntHelper::A( Func );  //error
IntHelper::B( Func );  //
IntHelper::C( Func );  //

however this fails to compile on gcc 4.5.1 ('error: no matching function for call to 'Helper<int>::A(<unresolved overloaded function type>)') and MSVC10 (cannot use function template 'void Func(const T &)' as a function argument and could not deduce template argument for 'overloaded function type' from 'overloaded function type').

Can someone explain why exactly, and is there a way around this?

edit ok I understand why it is not possible now; for the answers containing a workaround: in the actual code there are a lot of different Funcs, say 100, while there's only about 6 function like A, B and C...

like image 206
stijn Avatar asked Dec 27 '22 20:12

stijn


1 Answers

The form template<class> class Fun, whether as a declaration or as a template template parameter (like you have), is designed for class templates only, which Func isn't. It's a function template. Those have the form template</*parameters*/> Ret foo(/*parameters*/), and they aren't allowed as template template parameters.

Generally speaking function templates cannot be manipulated as much as class templates.

There is one situation where you can be spared the need to pass template parameters around:

// Deduces that Func<int> is meant
void (*p)(int) = Func;

Then you can pass p to A, B and C.

(Similarly if you have a function void f(void(*p)(int)); then a call of the form f(Func) is fine.)

like image 88
Luc Danton Avatar answered Feb 05 '23 11:02

Luc Danton