Sign in to follow this  
hiigara

[g++] "insufficient contextual information to determine type" what a heck?!

Recommended Posts

hiigara    108
I compiled this on g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3

[code]
template<typename T>
void dummy( T t )
{
}

template void dummy<int>( int );

void dummy2(int i)
{
}


main()
{

void(*fn)()=reinterpret_cast<void(*)()>( dummy<int> );
void(*fn2)()=reinterpret_cast<void(*)()>( static_cast<void(*)(int)>( dummy<int> ));
void(*fn3)()=reinterpret_cast<void(*)()>( dummy2 );
}
[/code]


fn fails with "insufficient contextual information to determine type".
Both fn2 and fn3 compile.
Now, it took me a whole afternoon goggling to find the double cast trick. Why can't g++ figure out the type of dummy<int> by itself???

Share this post


Link to post
Share on other sites
hiigara    108
This is the real code
[code]

/******************************************************************************/
class Alarm;
template<typename T>
struct Runalarmcontext{

T* p;
void ( T::* fn )( Alarm* _ap );
};

/*******************************************************************************
*******************************************************************************/
template<typename T>
void alarm_callback( Runalarmcontext<T>* _cp, Alarm* _ap )
{
( ( _cp->p )->*( _cp->fn ) )( _ap );
}

/******************************************************************************/
#define DECLARE_ALARM_CALLBACK( T, fn ) \
qdrive::Runalarmcontext<T> fn##Context; \
void fn( qdrive::Alarm* _ap );


#define CREATE_ALARM( T, _p, _fn, _Delta, _Repeat ) \
( _fn##Context.p = _p, _fn##Context.fn = &T::_fn, \
new qdrive::Alarm( reinterpret_cast<qdrive::Alarm::Callbackfn>( \
static_cast<void(*)( qdrive::Runalarmcontext<T>* _cp, qdrive::Alarm* _ap )>( \
qdrive::alarm_callback<T> )), &_fn##Context, _Delta, _Repeat ))

/******************************************************************************/
class Alarm {

public:

typedef void ( *Callbackfn )( void * _Context, Alarm* _ap ) ;

Alarm( Callbackfn _fn, void* _Context, timeval& _Delta,
bool _Repeat = false );
...
[/code]

When you create an alarm you pass in a static function and a context that will be the parameter of the static function.
Most of the times I would like a class member rather than a static function to handle the callback. So I created all the ugly stuff you see above the class Alarm.
With this in place, if I want the alarm to be handled by Foo::handle_alarm I simply write:
[code]

template
void qdrive::alarm_callback<Foo>( qdrive::Runalarmcontext<Foo>* _cp,
qdrive::Alarm* _ap );


struct Foo{

DECLARE_ALARM_CALLBACK(Foo, handle_alarm)


DECLARE_ALARM_CALLBACK(Foo, handle_alarm2)
...

void Foo::bar()
{

Alarm* p = CREATE_ALARM( Foo, this, handle_alarm,
500, false );
Alarm* p2 = CREATE_ALARM( Foo, this, handle_alarm2,
500, false );
}
[/code]

I am using this to cast away alarm_callback. Maybe there are better ways of accomplishing this.

Share this post


Link to post
Share on other sites
inavat    317
Possibly there are reasons you are avoiding boost. But if there are not, I highly suggest you look into [url="http://www.boost.org/doc/libs/1_47_0/doc/html/function.html"]boost::function[/url] and [url="http://www.boost.org/doc/libs/1_47_0/doc/html/signals.html"]boost::signals[/url]. They will make your life considerably easier.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this