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/config.hpp>
11 #include <boost/test/minimal.hpp>
13 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
14 int test_main(int, char* [])
18 #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
20 #include <boost/optional.hpp>
21 #include <boost/ref.hpp>
22 #include <boost/signals2.hpp>
26 struct max_or_default {
27 typedef T result_type;
28 template<typename InputIterator>
29 typename InputIterator::value_type
30 operator()(InputIterator first, InputIterator last) const
32 boost::optional<T> max;
33 for (; first != last; ++first)
37 if(!max) max = *first;
38 else max = (*first > max.get())? *first : max;
40 catch(const boost::bad_weak_ptr &)
43 if(max) return max.get();
49 make_int(int n, int cn) : N(n), CN(n) {}
50 int operator()() { return N; }
51 int operator()() const { return CN; }
58 struct make_increasing_int {
59 make_increasing_int() : n(N) {}
61 int operator()() const { return n++; }
66 int get_37() { return 37; }
78 boost::signals2::signal0<int, max_or_default<int>, std::string> s0;
79 boost::signals2::connection c2 = s0.connect(i2);
80 boost::signals2::connection c72 = s0.connect("72", i72);
81 boost::signals2::connection c62 = s0.connect("6x", i62);
82 boost::signals2::connection c42 = s0.connect(i42);
83 boost::signals2::connection c37 = s0.connect(&get_37);
85 BOOST_CHECK(s0() == 72);
88 BOOST_CHECK(s0() == 62);
90 c72.disconnect(); // Double-disconnect should be safe
91 BOOST_CHECK(s0() == 62);
93 s0.disconnect("72"); // Triple-disconect should be safe
94 BOOST_CHECK(s0() == 62);
96 // Also connect 63 in the same group as 62
97 s0.connect("6x", i63);
98 BOOST_CHECK(s0() == 63);
100 // Disconnect all of the 60's
102 BOOST_CHECK(s0() == 42);
105 BOOST_CHECK(s0() == 37);
108 BOOST_CHECK(s0() == 2);
111 BOOST_CHECK(s0() == 0);
115 boost::signals2::signal0<int, max_or_default<int> > s0;
116 boost::signals2::connection c2 = s0.connect(i2);
117 boost::signals2::connection c72 = s0.connect(i72);
118 boost::signals2::connection c62 = s0.connect(i62);
119 boost::signals2::connection c42 = s0.connect(i42);
121 const boost::signals2::signal0<int, max_or_default<int> >& cs0 = s0;
122 BOOST_CHECK(cs0() == 72);
126 make_increasing_int<7> i7;
127 make_increasing_int<10> i10;
129 boost::signals2::signal0<int, max_or_default<int> > s0;
130 boost::signals2::connection c7 = s0.connect(i7);
131 boost::signals2::connection c10 = s0.connect(i10);
133 BOOST_CHECK(s0() == 10);
134 BOOST_CHECK(s0() == 11);
141 boost::signals2::signal1<int, int, max_or_default<int> > s1;
143 s1.connect(std::negate<int>());
144 s1.connect(std::bind1st(std::multiplies<int>(), 2));
146 BOOST_CHECK(s1(1) == 2);
147 BOOST_CHECK(s1(-1) == 1);
151 test_signal_signal_connect()
153 typedef boost::signals2::signal1<int, int, max_or_default<int> > signal_type;
156 s1.connect(std::negate<int>());
158 BOOST_CHECK(s1(3) == -3);
163 s2.connect(std::bind1st(std::multiplies<int>(), 2));
164 s2.connect(std::bind1st(std::multiplies<int>(), -3));
166 BOOST_CHECK(s2(-3) == 9);
167 BOOST_CHECK(s1(3) == 6);
168 } // s2 goes out of scope and disconnects
170 BOOST_CHECK(s1(3) == -3);
172 // test auto-track of signal wrapped in a reference_wrapper
175 s1.connect(boost::cref(s2));
176 s2.connect(std::bind1st(std::multiplies<int>(), 2));
177 s2.connect(std::bind1st(std::multiplies<int>(), -3));
179 BOOST_CHECK(s2(-3) == 9);
180 BOOST_CHECK(s1(3) == 6);
181 } // s2 goes out of scope and disconnects
183 BOOST_CHECK(s1(3) == -3);
188 EventCounter() : count(0) {}
202 boost::signals2::signal0<void> s;
205 boost::signals2::scoped_connection c(s.connect(boost::ref(ec)));
206 BOOST_CHECK(ec.count == 0);
208 BOOST_CHECK(ec.count == 1);
211 BOOST_CHECK(ec.count == 1);
214 static void test_default_combiner()
216 boost::signals2::signal0<int> sig;
217 boost::optional<int> result;
219 BOOST_CHECK(!result);
221 sig.connect(make_int(0, 0));
224 BOOST_CHECK(*result == 0);
226 sig.connect(make_int(1, 1));
229 BOOST_CHECK(*result == 1);
232 template<typename ResultType>
233 ResultType disconnecting_slot(const boost::signals2::connection &conn, int)
239 #ifdef BOOST_NO_VOID_RETURNS
241 void disconnecting_slot<void>(const boost::signals2::connection &conn, int)
248 template<typename ResultType>
249 void test_extended_slot()
252 typedef boost::signals2::signal1<ResultType, int> signal_type;
253 typedef typename signal_type::extended_slot_type slot_type;
255 // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
256 ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
257 slot_type myslot(fp);
258 sig.connect_extended(myslot);
259 BOOST_CHECK(sig.num_slots() == 1);
261 BOOST_CHECK(sig.num_slots() == 0);
263 { // test 0 arg signal
264 typedef boost::signals2::signal0<ResultType> signal_type;
265 typedef typename signal_type::extended_slot_type slot_type;
267 // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
268 ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
269 slot_type myslot(fp, _1, 0);
270 sig.connect_extended(myslot);
271 BOOST_CHECK(sig.num_slots() == 1);
273 BOOST_CHECK(sig.num_slots() == 0);
275 // test disconnection by slot
277 typedef boost::signals2::signal1<ResultType, int> signal_type;
278 typedef typename signal_type::extended_slot_type slot_type;
280 // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
281 ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
282 slot_type myslot(fp);
283 sig.connect_extended(myslot);
284 BOOST_CHECK(sig.num_slots() == 1);
286 BOOST_CHECK(sig.num_slots() == 0);
292 typedef int result_type;
294 dummy_combiner(result_type return_value): _return_value(return_value)
296 template<typename SlotIterator>
297 result_type operator()(SlotIterator, SlotIterator)
299 return _return_value;
302 result_type _return_value;
308 typedef boost::signals2::signal0<int, dummy_combiner> signal_type;
309 signal_type sig(dummy_combiner(0));
310 BOOST_CHECK(sig() == 0);
311 BOOST_CHECK(sig.combiner()(0,0) == 0);
312 sig.set_combiner(dummy_combiner(1));
313 BOOST_CHECK(sig() == 1);
314 BOOST_CHECK(sig.combiner()(0,0) == 1);
320 typedef boost::signals2::signal0<int, dummy_combiner> signal_type;
321 signal_type sig1(dummy_combiner(1));
322 BOOST_CHECK(sig1() == 1);
323 signal_type sig2(dummy_combiner(2));
324 BOOST_CHECK(sig2() == 2);
327 BOOST_CHECK(sig1() == 2);
328 BOOST_CHECK(sig2() == 1);
332 BOOST_CHECK(sig1() == 1);
333 BOOST_CHECK(sig2() == 2);
337 test_main(int, char* [])
341 test_signal_signal_connect();
343 test_default_combiner();
344 test_extended_slot<void>();
345 test_extended_slot<int>();
351 #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES