dirk/C++/glibmm/sigc++-retype
Weingarten, 10-02-09
sigc++-retype – Flexible Callbacks
I'm very impressed about the elegance and the flexibility of the sigc++ library, especially, considering the fact that all is done in pure C++.
(Hot stuff!
)
Just a minor drawback are the terrible amount of error messages Microsoft's compiler spits out in the case of the slightest typo.
I'm new with this tool and not yet sensibilized where to look for the acutal mistake in such situation.
(Next time, I have such situation, I will add an example here.)
Thus, I ended up in my current application development with a bunch of errors and not an idea about the reason.
Finally, I decided for a small sample application to clarify the things a little bit.
Source Code
sigc++-retype.cc |
/** @file sample for sigc++ retype/bind
*
* Last CVS checkin:
* $Date: $
* $Author: scheff $
*/
/**************************************************************************/
// standard C/C++ header:
#include <iostream>
#include <string>
#include <vector>
// Gnome header:
#include <sigc++/sigc++.h>
#include <glibmm/init.h>
using namespace std;
/**************************************************************************/
/// provides a class emitting a signal
class Data {
// variables:
private:
/// the data
vector<int> _values;
// signals
public:
/// sent when a value has been added.
sigc::signal<void> sigAdd;
/** sent when a value has been removed.
* @param 1 removed value
* @param 2 iterator with former position of removed value
*/
sigc::signal<void, int, const vector<int>::const_iterator&> sigRemove;
// methods:
public:
/// @name Specific Access
//@{
/** returns data vector.
*
* @return data vector
*/
const vector<int>& get(void) const { return _values; }
/** adds a value to data.
*
* @param value a value
*/
void add(int value);
/** removes a value from data.
*
* @param it iterator
*/
void remove(vector<int>::const_iterator it);
//@}
};
/**************************************************************************/
void Data::add(int value)
{
_values.push_back(value);
sigAdd();
}
void Data::remove(vector<int>::const_iterator it)
{
int value = *it;
it = _values.erase(it);
sigRemove(value, it);
}
/**************************************************************************/
/// provides a stupid signal handler.
static void onSigStupid(void)
{
cout << "onSigStupid()" << endl;
}
/// provides another stupid signal handler.
static void onSigStupidText(const char *text)
{
cout << "onSigStupidText(\"" << text << "\")" << endl;
}
/// provides a signal handler for Data::sigAdd.
static void onAdd(void)
{
cout << "onAdd()." << endl;
}
/** provides a signal handler for Data::sigRemove.
*
* @param value removed value
* @param it iterator with former position of removed value (unused)
*/
static void onRemove(int value, const vector<int>::const_iterator&)
{
cout << "onRemove(" << value << ", it)" << endl;
}
/** provides another signal handler for Data::sigAdd.
*
* @param data calling instance
*/
static void onDataAdd(Data *pData)
{
cout << "onDataAdd(pData): " << pData->get().back() << endl;
}
/** provides a signal handler for Data::sigRemove.
*
* @param value removed value
* @param it iterator with former position of removed value (unused)
*/
static void onDataRemove(
Data *pData, int value, const vector<int>::const_iterator &it)
{
cout << "onDataRemove(pData, " << value << ", #"
<< (it - pData->get().begin()) << ')' << endl;
}
/** waits for user confirm.
*
* @param action text with next action
*/
static void pause(const char *action)
{
cout << "Press [ENTER] to " << action << ": " << flush;
string str; getline(cin, str);
}
/** provides the main function of application.
*
* @param argc number of command line arguments
* @param argv pointer to array of pointers to strings with command line
* arguments
* @return 0 ... application exited regularly\n
* else ... execution of application aborted
*/
int main(int argc, char *argv[])
{
Glib::init();
// stupid signal
pause("start");
{
// a stupid signal
sigc::signal<void> sigStupid; ///< void onSigStupid(void);
// connect stupid signal
sigc::connection connectionSigStupid
= sigStupid.connect(sigc::ptr_fun(&onSigStupid));
sigStupid.connect(sigc::bind<0>(
sigc::ptr_fun(&onSigStupidText), "static arg."));
// emit stupid signal
cout << "Emit sigStupid..." << endl;
sigStupid(); // i.e. sigStupid.emit();
// disconnect stupid signal
connectionSigStupid.disconnect();
// emit stupid signal again
cout << "Emit sigStupid..." << endl;
sigStupid(); // i.e. sigStupid.emit();
}
// signals for object state changes
pause("continue");
{
// wait for confirm
cout << "Press [ENTER] to continue: " << flush;
string str; getline(cin, str);
// a data item
Data data; data.add(10); data.add(20); data.add(30);
// connect matching signal handlers
data.sigAdd.connect(sigc::ptr_fun(&onAdd));
data.sigRemove.connect(sigc::ptr_fun(&onRemove));
// connect signal handlers with additional arg.
data.sigAdd.connect(sigc::bind<0>(
sigc::ptr_fun(&onDataAdd), &data));
data.sigRemove.connect(sigc::bind<0>(
sigc::ptr_fun(&onDataRemove), &data));
// perform some actions to emit signals
data.add(11); data.add(12); data.add(13);
cout << "Remove value #0 (" << *data.get().begin() << ')' << endl;
data.remove(data.get().begin());
cout << "Remove value #2 (" << *(data.get().begin() + 2) << ')' << endl;
data.remove(data.get().begin() + 2);
}
// done
pause("finish");
return 0;
}
|
Output
| Console: |
|---|
Press [ENTER] to continue: ↵
Emit sigStupid...
onSigStupid()
onSigStupidText("static arg.")
Emit sigStupid...
onSigStupidText("static arg.")
Press [ENTER] to continue: ↵
onAdd().
onDataAdd(pData): 11
onAdd().
onDataAdd(pData): 12
onAdd().
onDataAdd(pData): 13
Remove value #0 (10)
onRemove(10, it)
onDataRemove(pData, 10, #0)
Remove value #2 (11)
onRemove(11, it)
onDataRemove(pData, 11, #2)
Press [ENTER] to finish: ↵
|
Conclusion
sigc++'s retyping works like expected.
The actual mistake in my application must be caused by something completely different...
Files
Last modified: Sun Feb 21 18:47:17 2010