![]() |
![]() |
|
|
. . . and boost::lambda
Author / Автор: Sergey SatskiyPublication date / Опубликовано: 26.09.2005
|
void f( const double & Value ) { cout << "f called. Value: " << Value << endl; } |
Let us implement the entuty as a class with an interface like this:
struct CallbackStorage { CallbackStorage() { . . . } void insert( . . . ) { . . . } void operator() ( const double & val ) { . . . } }; |
It is necessary to note that all the code given here is a scetch only which should not be used in industrial software without considerable changes. For example the structure is used only to minor reduction of code typing.
The std::vector of boost::function objects suites well to store callback functions.
std::vector< boost::function< void ( const double & ) > > v;
|
Implementations of the member function insert(. . .) which provides a callback registration is trivial.
void insert( function< void ( const double & ) > func )
{
v.push_back( func );
}
|
The member function operator() provides external event processing i.e. calls all the registered callback functions and passes them the new value.
void operator() ( const double & val )
{
vector< function< void ( const double & ) > >::iterator k;
for ( k = v.begin(); k != v.end(); ++k )
{
(*k)( val );
}
}
|
The constructor is empty.
Now let us suppose that the similar code is used in an application which uses many double variables and allows registering / deregistering callback functions separately for each of them. Sometimes it is very convenient not to use an explicitly written callback function but to have an up to date value always "at hand". That is to use the following logic - to pass as a registration not a function but a reference to a variable which is supposed to be updated as soon as an entity is updated.
In other words the following overloaded member function insert() is required.
void insert( double & Ref ) { . . . }
|
What to do with the given reference? The brutal force option is to have another list in the CallbackStorage and to have another cycle in the operator() which makes assignments. This option does not seem to be very elegant.
The boost::lambda library allows to avoid having the second container as well as the second cycle. The overloaded member function insert() can be implemented as follows:
void insert( double & Ref )
{
function< void ( const double & ) > g = ( var( Ref ) = _1 );
v.push_back( g );
}
|
It is very laconically!
The corresponding source code can be found at the author's web site: http://satsky.spb.ru.