1 // Boost.Signals library
3 // Copyright Douglas Gregor 2001-2003. Use, modification and
4 // distribution is subject to the Boost Software License, Version
5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // For more information, see http://www.boost.org
10 #include <boost/bind.hpp>
11 #include <boost/config.hpp>
12 #include <boost/test/minimal.hpp>
14 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
15 int test_main(int, char* [])
19 #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
21 #include <boost/optional.hpp>
22 #include <boost/ref.hpp>
23 #include <boost/signals2.hpp>
27 struct max_or_default
{
28 typedef T result_type
;
29 template<typename InputIterator
>
30 typename
InputIterator::value_type
31 operator()(InputIterator first
, InputIterator last
) const
33 boost::optional
<T
> max
;
34 for (; first
!= last
; ++first
)
38 if(!max
) max
= *first
;
39 else max
= (*first
> max
.get())? *first
: max
;
41 catch(const boost::bad_weak_ptr
&)
44 if(max
) return max
.get();
50 make_int(int n
, int cn
) : N(n
), CN(n
) {}
51 int operator()() { return N
; }
52 int operator()() const { return CN
; }
59 struct make_increasing_int
{
60 make_increasing_int() : n(N
) {}
62 int operator()() const { return n
++; }
67 int get_37() { return 37; }
79 boost::signals2::signal0
<int, max_or_default
<int>, std::string
> s0
;
80 boost::signals2::connection c2
= s0
.connect(i2
);
81 boost::signals2::connection c72
= s0
.connect("72", i72
);
82 boost::signals2::connection c62
= s0
.connect("6x", i62
);
83 boost::signals2::connection c42
= s0
.connect(i42
);
84 boost::signals2::connection c37
= s0
.connect(&get_37
);
86 BOOST_CHECK(s0() == 72);
89 BOOST_CHECK(s0() == 62);
91 c72
.disconnect(); // Double-disconnect should be safe
92 BOOST_CHECK(s0() == 62);
94 s0
.disconnect("72"); // Triple-disconect should be safe
95 BOOST_CHECK(s0() == 62);
97 // Also connect 63 in the same group as 62
98 s0
.connect("6x", i63
);
99 BOOST_CHECK(s0() == 63);
101 // Disconnect all of the 60's
103 BOOST_CHECK(s0() == 42);
106 BOOST_CHECK(s0() == 37);
109 BOOST_CHECK(s0() == 2);
112 BOOST_CHECK(s0() == 0);
116 boost::signals2::signal0
<int, max_or_default
<int> > s0
;
117 boost::signals2::connection c2
= s0
.connect(i2
);
118 boost::signals2::connection c72
= s0
.connect(i72
);
119 boost::signals2::connection c62
= s0
.connect(i62
);
120 boost::signals2::connection c42
= s0
.connect(i42
);
122 const boost::signals2::signal0
<int, max_or_default
<int> >& cs0
= s0
;
123 BOOST_CHECK(cs0() == 72);
127 make_increasing_int
<7> i7
;
128 make_increasing_int
<10> i10
;
130 boost::signals2::signal0
<int, max_or_default
<int> > s0
;
131 boost::signals2::connection c7
= s0
.connect(i7
);
132 boost::signals2::connection c10
= s0
.connect(i10
);
134 BOOST_CHECK(s0() == 10);
135 BOOST_CHECK(s0() == 11);
142 boost::signals2::signal1
<int, int, max_or_default
<int> > s1
;
144 s1
.connect(std::negate
<int>());
145 s1
.connect(boost::bind(std::multiplies
<int>(), 2, _1
));
147 BOOST_CHECK(s1(1) == 2);
148 BOOST_CHECK(s1(-1) == 1);
152 test_signal_signal_connect()
154 typedef boost::signals2::signal1
<int, int, max_or_default
<int> > signal_type
;
157 s1
.connect(std::negate
<int>());
159 BOOST_CHECK(s1(3) == -3);
164 s2
.connect(boost::bind(std::multiplies
<int>(), 2, _1
));
165 s2
.connect(boost::bind(std::multiplies
<int>(), -3, _1
));
167 BOOST_CHECK(s2(-3) == 9);
168 BOOST_CHECK(s1(3) == 6);
169 } // s2 goes out of scope and disconnects
171 BOOST_CHECK(s1(3) == -3);
173 // test auto-track of signal wrapped in a reference_wrapper
176 s1
.connect(boost::cref(s2
));
177 s2
.connect(boost::bind(std::multiplies
<int>(), 2, _1
));
178 s2
.connect(boost::bind(std::multiplies
<int>(), -3, _1
));
180 BOOST_CHECK(s2(-3) == 9);
181 BOOST_CHECK(s1(3) == 6);
182 } // s2 goes out of scope and disconnects
184 BOOST_CHECK(s1(3) == -3);
189 EventCounter() : count(0) {}
203 boost::signals2::signal0
<void> s
;
206 boost::signals2::scoped_connection
c(s
.connect(boost::ref(ec
)));
207 BOOST_CHECK(ec
.count
== 0);
209 BOOST_CHECK(ec
.count
== 1);
212 BOOST_CHECK(ec
.count
== 1);
215 static void test_default_combiner()
217 boost::signals2::signal0
<int> sig
;
218 boost::optional
<int> result
;
220 BOOST_CHECK(!result
);
222 sig
.connect(make_int(0, 0));
225 BOOST_CHECK(*result
== 0);
227 sig
.connect(make_int(1, 1));
230 BOOST_CHECK(*result
== 1);
233 template<typename ResultType
>
234 ResultType
disconnecting_slot(const boost::signals2::connection
&conn
, int)
240 #ifdef BOOST_NO_VOID_RETURNS
242 void disconnecting_slot
<void>(const boost::signals2::connection
&conn
, int)
249 template<typename ResultType
>
250 void test_extended_slot()
253 typedef boost::signals2::signal1
<ResultType
, int> signal_type
;
254 typedef typename
signal_type::extended_slot_type slot_type
;
256 // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
257 ResultType (*fp
)(const boost::signals2::connection
&conn
, int) = &disconnecting_slot
<ResultType
>;
258 slot_type
myslot(fp
);
259 sig
.connect_extended(myslot
);
260 BOOST_CHECK(sig
.num_slots() == 1);
262 BOOST_CHECK(sig
.num_slots() == 0);
264 { // test 0 arg signal
265 typedef boost::signals2::signal0
<ResultType
> signal_type
;
266 typedef typename
signal_type::extended_slot_type slot_type
;
268 // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
269 ResultType (*fp
)(const boost::signals2::connection
&conn
, int) = &disconnecting_slot
<ResultType
>;
270 slot_type
myslot(fp
, _1
, 0);
271 sig
.connect_extended(myslot
);
272 BOOST_CHECK(sig
.num_slots() == 1);
274 BOOST_CHECK(sig
.num_slots() == 0);
276 // test disconnection by slot
278 typedef boost::signals2::signal1
<ResultType
, int> signal_type
;
279 typedef typename
signal_type::extended_slot_type slot_type
;
281 // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
282 ResultType (*fp
)(const boost::signals2::connection
&conn
, int) = &disconnecting_slot
<ResultType
>;
283 slot_type
myslot(fp
);
284 sig
.connect_extended(myslot
);
285 BOOST_CHECK(sig
.num_slots() == 1);
287 BOOST_CHECK(sig
.num_slots() == 0);
293 typedef int result_type
;
295 dummy_combiner(result_type return_value
): _return_value(return_value
)
297 template<typename SlotIterator
>
298 result_type
operator()(SlotIterator
, SlotIterator
)
300 return _return_value
;
303 result_type _return_value
;
309 typedef boost::signals2::signal0
<int, dummy_combiner
> signal_type
;
310 signal_type
sig(dummy_combiner(0));
311 BOOST_CHECK(sig() == 0);
312 BOOST_CHECK(sig
.combiner()(0,0) == 0);
313 sig
.set_combiner(dummy_combiner(1));
314 BOOST_CHECK(sig() == 1);
315 BOOST_CHECK(sig
.combiner()(0,0) == 1);
321 typedef boost::signals2::signal0
<int, dummy_combiner
> signal_type
;
322 signal_type
sig1(dummy_combiner(1));
323 BOOST_CHECK(sig1() == 1);
324 signal_type
sig2(dummy_combiner(2));
325 BOOST_CHECK(sig2() == 2);
328 BOOST_CHECK(sig1() == 2);
329 BOOST_CHECK(sig2() == 1);
333 BOOST_CHECK(sig1() == 1);
334 BOOST_CHECK(sig2() == 2);
338 test_main(int, char* [])
342 test_signal_signal_connect();
344 test_default_combiner();
345 test_extended_slot
<void>();
346 test_extended_slot
<int>();
352 #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES