1 // Boost.Signals library
3 // Copyright Frank Mori Hess 2008-2009.
4 // Copyright Douglas Gregor 2001-2003.
6 // Use, modification and
7 // distribution is subject to the Boost Software License, Version
8 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
11 // For more information, see http://www.boost.org
13 #include <boost/bind.hpp>
14 #include <boost/optional.hpp>
15 #include <boost/test/minimal.hpp>
16 #include <boost/signals2.hpp>
22 struct max_or_default
{
23 typedef T result_type
;
24 template<typename InputIterator
>
25 typename
InputIterator::value_type
26 operator()(InputIterator first
, InputIterator last
) const
28 boost::optional
<T
> max
;
29 for (; first
!= last
; ++first
)
33 if(!max
) max
= *first
;
34 else max
= (*first
> max
.get())? *first
: max
;
36 catch(const boost::bad_weak_ptr
&)
39 if(max
) return max
.get();
45 make_int(int n
, int cn
) : N(n
), CN(cn
) {}
47 int operator()() { return N
; }
48 int operator()() const { return CN
; }
55 struct make_increasing_int
{
56 make_increasing_int() : n(N
) {}
58 int operator()() const { return n
++; }
73 boost::signals2::signal
<int (), max_or_default
<int> > s0
;
75 std::cout
<< "sizeof(signal) = " << sizeof(s0
) << std::endl
;
76 boost::signals2::connection c2
= s0
.connect(i2
);
77 boost::signals2::connection c72
= s0
.connect(72, i72
);
78 boost::signals2::connection c62
= s0
.connect(60, i62
);
79 boost::signals2::connection c42
= s0
.connect(i42
);
81 BOOST_CHECK(s0() == 72);
84 BOOST_CHECK(s0() == 62);
86 c72
.disconnect(); // Double-disconnect should be safe
87 BOOST_CHECK(s0() == 62);
89 s0
.disconnect(72); // Triple-disconect should be safe
90 BOOST_CHECK(s0() == 62);
92 // Also connect 63 in the same group as 62
94 BOOST_CHECK(s0() == 63);
96 // Disconnect all of the 60's
98 BOOST_CHECK(s0() == 42);
101 BOOST_CHECK(s0() == 2);
104 BOOST_CHECK(s0() == 0);
108 boost::signals2::signal
<int (), max_or_default
<int> > s0
;
109 boost::signals2::connection c2
= s0
.connect(i2
);
110 boost::signals2::connection c72
= s0
.connect(i72
);
111 boost::signals2::connection c62
= s0
.connect(i62
);
112 boost::signals2::connection c42
= s0
.connect(i42
);
114 const boost::signals2::signal
<int (), max_or_default
<int> >& cs0
= s0
;
115 BOOST_CHECK(cs0() == 72);
119 make_increasing_int
<7> i7
;
120 make_increasing_int
<10> i10
;
122 boost::signals2::signal
<int (), max_or_default
<int> > s0
;
123 boost::signals2::connection c7
= s0
.connect(i7
);
124 boost::signals2::connection c10
= s0
.connect(i10
);
126 BOOST_CHECK(s0() == 10);
127 BOOST_CHECK(s0() == 11);
134 boost::signals2::signal
<int (int value
), max_or_default
<int> > s1
;
136 s1
.connect(std::negate
<int>());
137 s1
.connect(boost::bind(std::multiplies
<int>(), 2, _1
));
139 BOOST_CHECK(s1(1) == 2);
140 BOOST_CHECK(s1(-1) == 1);
144 test_signal_signal_connect()
146 typedef boost::signals2::signal
<int (int value
), max_or_default
<int> > signal_type
;
149 s1
.connect(std::negate
<int>());
151 BOOST_CHECK(s1(3) == -3);
156 s2
.connect(boost::bind(std::multiplies
<int>(), 2, _1
));
157 s2
.connect(boost::bind(std::multiplies
<int>(), -3, _1
));
159 BOOST_CHECK(s2(-3) == 9);
160 BOOST_CHECK(s1(3) == 6);
161 } // s2 goes out of scope and disconnects
162 BOOST_CHECK(s1(3) == -3);
165 template<typename ResultType
>
166 ResultType
disconnecting_slot(const boost::signals2::connection
&conn
, int)
172 #ifdef BOOST_NO_VOID_RETURNS
174 void disconnecting_slot
<void>(const boost::signals2::connection
&conn
, int)
181 template<typename ResultType
>
182 void test_extended_slot()
185 typedef boost::signals2::signal
<ResultType (int)> signal_type
;
186 typedef typename
signal_type::extended_slot_type slot_type
;
188 // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
189 ResultType (*fp
)(const boost::signals2::connection
&conn
, int) = &disconnecting_slot
<ResultType
>;
190 slot_type
myslot(fp
);
191 sig
.connect_extended(myslot
);
192 BOOST_CHECK(sig
.num_slots() == 1);
194 BOOST_CHECK(sig
.num_slots() == 0);
196 { // test 0 arg signal
197 typedef boost::signals2::signal
<ResultType ()> signal_type
;
198 typedef typename
signal_type::extended_slot_type slot_type
;
200 // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
201 ResultType (*fp
)(const boost::signals2::connection
&conn
, int) = &disconnecting_slot
<ResultType
>;
202 slot_type
myslot(fp
, _1
, 0);
203 sig
.connect_extended(myslot
);
204 BOOST_CHECK(sig
.num_slots() == 1);
206 BOOST_CHECK(sig
.num_slots() == 0);
208 // test disconnection by slot
210 typedef boost::signals2::signal
<ResultType (int)> signal_type
;
211 typedef typename
signal_type::extended_slot_type slot_type
;
213 // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
214 ResultType (*fp
)(const boost::signals2::connection
&conn
, int) = &disconnecting_slot
<ResultType
>;
215 slot_type
myslot(fp
);
216 sig
.connect_extended(myslot
);
217 BOOST_CHECK(sig
.num_slots() == 1);
219 BOOST_CHECK(sig
.num_slots() == 0);
223 void increment_arg(int &value
)
229 test_reference_args()
231 typedef boost::signals2::signal
<void (int &)> signal_type
;
234 s1
.connect(&increment_arg
);
237 BOOST_CHECK(value
== 1);
243 typedef boost::signals2::signal
<int (double, long)> signal_type
;
244 typedef signal_type::slot_type slot_type
;
246 BOOST_CHECK(typeid(signal_type::slot_result_type
) == typeid(int));
247 BOOST_CHECK(typeid(signal_type::result_type
) == typeid(boost::optional
<int>));
248 BOOST_CHECK(typeid(signal_type::arg
<0>::type
) == typeid(double));
249 BOOST_CHECK(typeid(signal_type::arg
<1>::type
) == typeid(long));
250 BOOST_CHECK(typeid(signal_type::arg
<0>::type
) == typeid(signal_type::first_argument_type
));
251 BOOST_CHECK(typeid(signal_type::arg
<1>::type
) == typeid(signal_type::second_argument_type
));
252 BOOST_CHECK(typeid(signal_type::signature_type
) == typeid(int (double, long)));
253 BOOST_CHECK(signal_type::arity
== 2);
255 BOOST_CHECK(typeid(slot_type::result_type
) == typeid(signal_type::slot_result_type
));
256 BOOST_CHECK(typeid(slot_type::arg
<0>::type
) == typeid(signal_type::arg
<0>::type
));
257 BOOST_CHECK(typeid(slot_type::arg
<1>::type
) == typeid(signal_type::arg
<1>::type
));
258 BOOST_CHECK(typeid(slot_type::arg
<0>::type
) == typeid(slot_type::first_argument_type
));
259 BOOST_CHECK(typeid(slot_type::arg
<1>::type
) == typeid(slot_type::second_argument_type
));
260 BOOST_CHECK(typeid(slot_type::signature_type
) == typeid(signal_type::signature_type
));
261 BOOST_CHECK(slot_type::arity
== signal_type::arity
);
263 typedef boost::signals2::signal
<void (short)> unary_signal_type
;
264 BOOST_CHECK(typeid(unary_signal_type::slot_result_type
) == typeid(void));
265 BOOST_CHECK(typeid(unary_signal_type::argument_type
) == typeid(short));
266 BOOST_CHECK(typeid(unary_signal_type::slot_type::argument_type
) == typeid(short));
272 typedef int result_type
;
274 dummy_combiner(result_type return_value
): _return_value(return_value
)
276 template<typename SlotIterator
>
277 result_type
operator()(SlotIterator
, SlotIterator
)
279 return _return_value
;
282 result_type _return_value
;
288 typedef boost::signals2::signal
<int (), dummy_combiner
> signal_type
;
289 signal_type
sig(dummy_combiner(0));
290 BOOST_CHECK(sig() == 0);
291 BOOST_CHECK(sig
.combiner()(0,0) == 0);
292 sig
.set_combiner(dummy_combiner(1));
293 BOOST_CHECK(sig() == 1);
294 BOOST_CHECK(sig
.combiner()(0,0) == 1);
300 typedef boost::signals2::signal
<int (), dummy_combiner
> signal_type
;
301 signal_type
sig1(dummy_combiner(1));
302 BOOST_CHECK(sig1() == 1);
303 signal_type
sig2(dummy_combiner(2));
304 BOOST_CHECK(sig2() == 2);
307 BOOST_CHECK(sig1() == 2);
308 BOOST_CHECK(sig2() == 1);
312 BOOST_CHECK(sig1() == 1);
313 BOOST_CHECK(sig2() == 2);
318 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
319 typedef boost::signals2::signal
<int (), dummy_combiner
> signal_type
;
320 signal_type
sig1(dummy_combiner(1));
321 BOOST_CHECK(sig1() == 1);
322 signal_type
sig2(dummy_combiner(2));
323 BOOST_CHECK(sig2() == 2);
325 sig1
= std::move(sig2
);
326 BOOST_CHECK(sig1() == 2);
328 signal_type
sig3(std::move(sig1
));
329 BOOST_CHECK(sig3() == 2);
330 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
334 test_main(int, char* [])
338 test_signal_signal_connect();
339 test_extended_slot
<void>();
340 test_extended_slot
<int>();
341 test_reference_args();