C++ Template metaprogramming : Why this code can't compile?

I

Ik Pil

template <typename R, typename TT>
class FuncObject
{
typedef R ( *func_ptr )( TT );
public:
FuncObject( func_ptr p )
: p_( p )
{
}
private:
func_ptr p_;
};



template <typename R, typename TT>
FuncObject<R, TT> func_wrapper( R ( *pfunc )( TT ) )
{
return FuncObject<R, TT>( pfunc );
}



void f( void )
{
}



int main( void )
{
func_wrapper( f ); // can't
}
 
K

Kai-Uwe Bux

Ik said:
template <typename R, typename TT>
class FuncObject
{
typedef R ( *func_ptr )( TT );
public:
FuncObject( func_ptr p )
: p_( p )
{
}
private:
func_ptr p_;
};



template <typename R, typename TT>
FuncObject<R, TT> func_wrapper( R ( *pfunc )( TT ) )
{
return FuncObject<R, TT>( pfunc );
}



void f( void )
{
}



int main( void )
{
func_wrapper( f ); // can't
}

The templates FuncObject and func_wrapper expect a pointer to a function of
one argument. The Function f takes no arguments. Therefore, you have a
mismatch.


Best

Kai-Uwe Bux
 
R

red floyd

Ik said:
template <typename R, typename TT>
class FuncObject
{
typedef R ( *func_ptr )( TT );
public:
FuncObject( func_ptr p )
: p_( p )
{
}
private:
func_ptr p_;
};



template <typename R, typename TT>
FuncObject<R, TT> func_wrapper( R ( *pfunc )( TT ) )
{
return FuncObject<R, TT>( pfunc );
}



void f( void )
{
}



int main( void )
{
func_wrapper( f ); // can't
}

This is not metaprogramming, just template programming.
You can also minimize the example by removing all references to
FuncObject.

And it doesn't work for me, either with g++ 3.4.4 or with Comeau
online. I can't figure out why. It complains that there's no
match, even when I pass &f instead of just f.
 
R

red floyd

Kai-Uwe Bux said:
The templates FuncObject and func_wrapper expect a pointer to a function of
one argument. The Function f takes no arguments. Therefore, you have a
mismatch.

Kai-Uwe, can you tell me what's worng with this one? Is it the same
issue, even when I explicitly specify void?

template <typename R, typename TT>
void func_wrapper( R ( *pfunc )( TT ) )
{
}

void f( )
{
}

int main( )
{
func_wrapper<void,void>( &f ); // can't
}
 
I

Ian Collins

red said:
Kai-Uwe, can you tell me what's worng with this one? Is it the same
issue, even when I explicitly specify void?

template <typename R, typename TT>
void func_wrapper( R ( *pfunc )( TT ) )
{
}

void f( )
{
}

int main( )
{
func_wrapper<void,void>( &f ); // can't
}

void isn't a parameter type.
 
I

Ian Collins

Ik said:
template <typename R, typename TT>
class FuncObject
{
typedef R ( *func_ptr )( TT );
public:
FuncObject( func_ptr p )
: p_( p )
{
}
private:
func_ptr p_;
};

template <typename R, typename TT>
FuncObject<R, TT> func_wrapper( R ( *pfunc )( TT ) )
{
return FuncObject<R, TT>( pfunc );
}

void f( void )
{
}

int main( void )
{
func_wrapper( f ); // can't
}

You can't use void as a function parameter type in this way. You will
have to specialise your object and function for functions with no
parameters.

There isn't any metaprogramming in your code.
 
I

Ian Collins

Ian said:
void isn't a parameter type.
I though I'd better try it and I added a specialisation for func_wrapper
only:

template <typename R>
FuncObject<R,void> func_wrapper( R ( *pfunc )() )
{
return FuncObject<R,void>( pfunc );
}

Which gives a more helpful error message from Sun CC:

line 4: Warning (Anachronism): A typedef for "void" is not a valid way
to declare a function without arguments.
 
I

Ik Pil

The templates FuncObject and func_wrapper expect a pointer to a function of
one argument. The Function f takes no arguments. Therefore, you have a
mismatch.

Best

Kai-Uwe Bux

Thank you, very mush!
I love you!
 
N

Noah Roberts

You got your answer but I'd also seriously suggest that unless you're
doing this as an intellectual exercise that you use boost::function in
combination with boost::bind. The authors have already gone to the work
of addressing a lot of touchy concerns that would end up biting you in
the neck.
 
K

Kai-Uwe Bux

red said:
Kai-Uwe, can you tell me what's worng with this one? Is it the same
issue, even when I explicitly specify void?

template <typename R, typename TT>
void func_wrapper( R ( *pfunc )( TT ) )
{
}

void f( )
{
}

int main( )
{
func_wrapper<void,void>( &f ); // can't
}

Yes, it's the same.

The standard has a rather vague provison in [8.5.3/2]

...The parameter list (void) is equivalent to the empty parameter list.
Except for this special case, void shall not be a parameter type (though
types derived from void, such as void*, can). ...

but it also has something that undoubtedly applies: a provision for when
type deduction fails. In [14.8.2/2] it says:

... Type deduction may fail for the following reasons:
...
- Attempting to create a function type in which a parameter has a
type of void.


Best

Kai-Uwe Bux
 
J

James Kanze

red floyd wrote:

[...]
Yes, it's the same.
The standard has a rather vague provison in [8.5.3/2]
...The parameter list (void) is equivalent to the empty parameter list.
Except for this special case, void shall not be a parameter type (though
types derived from void, such as void*, can). ...

Most importantly, in this case, void is not a type; it's just a
keyword with a special meaning. Thus, something like:

typedef void toto ;
void f( toto ) ;

is not legal.
but it also has something that undoubtedly applies: a
provision for when type deduction fails. In [14.8.2/2] it
says:
... Type deduction may fail for the following reasons:
- Attempting to create a function type in which a parameter has a
type of void.

Exactly. Because a parameter cannot have the type void.
 
R

red floyd

Kai-Uwe Bux said:
red said:
Kai-Uwe, can you tell me what's worng with this one? Is it the same
issue, even when I explicitly specify void?

template <typename R, typename TT>
void func_wrapper( R ( *pfunc )( TT ) )
{
}

void f( )
{
}

int main( )
{
func_wrapper<void,void>( &f ); // can't
}

Yes, it's the same.

The standard has a rather vague provison in [8.5.3/2]

...The parameter list (void) is equivalent to the empty parameter list.
Except for this special case, void shall not be a parameter type (though
types derived from void, such as void*, can). ...

but it also has something that undoubtedly applies: a provision for when
type deduction fails. In [14.8.2/2] it says:

... Type deduction may fail for the following reasons:
...
- Attempting to create a function type in which a parameter has a
type of void.
Ah. Thank you.
 
M

mail.dsp

There are two problems:

1. Here type of f() is "void (*) (void)" and compiler is deducing R
and TT using type of f() which is not possible.
2. For void you need to specialize.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top