Reputation: 11
As boost_offical_web_site says, boost::function is not comparable。but I am doubt about the usage:
#include <boost/signals2.hpp>
class B {
public:
~B() {
printf("B dealloc:%p\n", this);
}
void OnSignalActive(void) {
printf("B get signal address:%p\n", this);
}
};
void test05() {
boost::signals2::signal<void (void)> signalConnection;
B b;
auto v = boost::bind(&B::OnSignalActive, &b);
auto u = boost::bind(&B::OnSignalActive, &b);
// if (v == u) {//compile error
//
// }
boost::signals2::slot<void (void)> slot1(v);
boost::signals2::slot<void (void)> slot2(v);
// if (slot1.slot_function() == slot2) {//compile error
//
// }
boost::signals2::connection conn = signalConnection.connect(v);
signalConnection();
signalConnection.disconnect(u);
signalConnection();
}
int main(int argc, const char * argv[]) {
test05();
return 0;
}
the code signalConnection.disconnect(u) can disconnect signal and runs well.I suspend boost do comparision by slot. so I debug into source:
void do_disconnect(const T &slot, mpl::bool_<false> /* is_group */)
{
shared_ptr<invocation_state> local_state =
get_readable_state();
typename connection_list_type::iterator it;
for(it = local_state->connection_bodies().begin();
it != local_state->connection_bodies().end(); ++it)
{
garbage_collecting_lock<connection_body_base> lock(**it);
if((*it)->nolock_nograb_connected() == false) continue;
if((*it)->slot().slot_function() == slot)
{
(*it)->nolock_disconnect(lock);
}else
{
// check for wrapped extended slot
bound_extended_slot_function_type *fp;
fp = (*it)->slot().slot_function().template target<bound_extended_slot_function_type>();
if(fp && *fp == slot)
{
(*it)->nolock_disconnect(lock);
}
}
}
}
found that inner uses == to disconnect.one is slot_function(actual boost::function) and another is slot. But when I manually create boost::signals2::slot. could not compare!
/main.cpp:303:31: note: in instantiation of function template specialization 'boost::operator==<boost::signals2::slot<void ()>>' requested here
if (slot1.slot_function() == slot2) {//compile error
I confused very much.
how can boost disconnect like this? using slot & slot_function? why manually create could not compare?
can someone help me!3Q in advance.
help me & answer the question.
Upvotes: 1
Views: 60
Reputation: 392833
The actual line is
if((*it)->slot().slot_function().contains(slot))
Which indeed ends up comparing the functions type-erased targets, if the typeid matches. This behaviour may be overrided for your own types by creating your own overload of function_equal
to be found by ADL. (See also Comparing Boost.Function Objects)
Boost bind expressions can be compared if the bound expressions can be. Replacing with std::bind
makes it fail.
It's an implementation but indeed putting a stub like
friend bool function_equal_impl(auto&&...) { return false; }
Makes it compile with std::bind. Of course, it won't really compare now.
In short, don't use disconnect(handler)
unless your handlers are comparable. If you have handlers that cannot be compared, use scoped_connection
instead:
#include <boost/signals2.hpp>
namespace signals2 = boost::signals2;
#define TRACE(code) do { printf("%d: %s\n", __LINE__, #code); code; } while (0)
void test05() {
signals2::signal<void()> signal;
signals2::scoped_connection v = signal.connect([] { printf("Handler: V\n"); });
signals2::scoped_connection u = signal.connect([] { printf("Handler: U\n"); });
TRACE(signal());
TRACE(v.disconnect());
TRACE(signal());
}
Printing Live On Coliru
11: signal()
Handler: V
Handler: U
12: v.disconnect()
13: signal()
Handler: U
Upvotes: 0