This post is very old. Please bear in mind that information here might be incorrect or obsolete, and links can be broken. If something seems wrong, please feel free to comment or contact me and I'll update the post.
Recently, I came across a problem with Boost::Signal. I wanted to use them inside a std::map so I could map signals to categories, and this turned out to be not as simple as one might think.
Problem
The main problem is that boost::signal is noncopyable, meaning you can’t use the assignment operator “=” at all. This prevents the straightforward use in any STL container, as those depend on the assignment operator. You can of course have explicit instances of boost::signal, but you can’t use them directly in a container, let alone add and remove them dynamically.
Solution
The first solution I tried was to store pointers (in my case, boost::shared_ptr<>) to the signals, and fill the map with those. This works, but it is a bit cumbersome to maintain all the pointers and have new all around the place. Fortunately, another boost library comes to the rescue, boost::ptr_map from the Boost Pointer Container library. It has two specialities I came across (using boost 1.33.1 beta from 8th November).
- Its
insert ()function takes a non-const reference as key, unlike thestd::map. Be aware of that, as it can lead to hard-to-find compiler errors. - The dereferencing was non-standard, in my case I had to use
(iterator_to_ptr_map)(params_for_signal), I supposed I would have to add some “*” somewhere but somehow the map didn’t need it.
Will try with Boost 1.33.1 final and report if there is any difference to the beta.
Related posts:
No difference with Boost 1.33.1 final
Could someone explain, why boost::signal is noncopyable!?!?
Take a look at the rationale at http://boost.org/doc/html/signals.html, specifically at “trackable copying behavior”.
Basically, if you copy a signal, how to you inform those who are registered that they are now registered at a new signal? There is no way to do this reliably.
When i faced with a problem that boost::signal is noncopyable then i used dynamic object.
typedef boost::signal signal_exec;
typedef boost::signals::connection sign_conn;
// creating and setting to the std::map
std::map::iterator it;
sign_conn s_c;
it = ExecHandlers.find(id);
if (it != ExecHandlers.end()) {
FLD_LOG(LOG_ERROR, “exec id = %d already exist”, id);
} else {
signal_exec *exec = new signal_exec();
s_c = exec->connect(exec_handler);
if (!s_c.connected()) {
FLD_LOG(LOG_ERROR, “SetExecHandler failed”);
} else {
ExecHandlers.insert(std::make_pair(id, exec));
}
}
return s_c;
}
using:
std::map::iterator it;
it = ExecHandlers.find(sql.id);
if (it == ExecHandlers.end()) {
FLD_LOG(LOG_ERROR, “exec id = %d not found in FireExecHandler”, sql.id);
} else {
(*it->second) (res, error, sql); // calling
}