123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- // Boost.Signals library
- // Copyright Frank Mori Hess 2008-2009.
- // Copyright Douglas Gregor 2001-2003.
- //
- // Use, modification and
- // distribution is subject to the Boost Software License, Version
- // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- // For more information, see http://www.boost.org
- #include <boost/bind.hpp>
- #include <boost/optional.hpp>
- #include <boost/test/minimal.hpp>
- #include <boost/signals2.hpp>
- #include <functional>
- #include <iostream>
- #include <typeinfo>
- template<typename T>
- struct max_or_default {
- typedef T result_type;
- template<typename InputIterator>
- typename InputIterator::value_type
- operator()(InputIterator first, InputIterator last) const
- {
- boost::optional<T> max;
- for (; first != last; ++first)
- {
- try
- {
- if(!max) max = *first;
- else max = (*first > max.get())? *first : max;
- }
- catch(const boost::bad_weak_ptr &)
- {}
- }
- if(max) return max.get();
- return T();
- }
- };
- struct make_int {
- make_int(int n, int cn) : N(n), CN(cn) {}
- int operator()() { return N; }
- int operator()() const { return CN; }
- int N;
- int CN;
- };
- template<int N>
- struct make_increasing_int {
- make_increasing_int() : n(N) {}
- int operator()() const { return n++; }
- mutable int n;
- };
- static void
- test_zero_args()
- {
- make_int i42(42, 41);
- make_int i2(2, 1);
- make_int i72(72, 71);
- make_int i63(63, 63);
- make_int i62(62, 61);
- {
- boost::signals2::signal<int (), max_or_default<int> > s0;
- std::cout << "sizeof(signal) = " << sizeof(s0) << std::endl;
- boost::signals2::connection c2 = s0.connect(i2);
- boost::signals2::connection c72 = s0.connect(72, i72);
- boost::signals2::connection c62 = s0.connect(60, i62);
- boost::signals2::connection c42 = s0.connect(i42);
- BOOST_CHECK(s0() == 72);
- s0.disconnect(72);
- BOOST_CHECK(s0() == 62);
- c72.disconnect(); // Double-disconnect should be safe
- BOOST_CHECK(s0() == 62);
- s0.disconnect(72); // Triple-disconect should be safe
- BOOST_CHECK(s0() == 62);
- // Also connect 63 in the same group as 62
- s0.connect(60, i63);
- BOOST_CHECK(s0() == 63);
- // Disconnect all of the 60's
- s0.disconnect(60);
- BOOST_CHECK(s0() == 42);
- c42.disconnect();
- BOOST_CHECK(s0() == 2);
- c2.disconnect();
- BOOST_CHECK(s0() == 0);
- }
- {
- boost::signals2::signal<int (), max_or_default<int> > s0;
- boost::signals2::connection c2 = s0.connect(i2);
- boost::signals2::connection c72 = s0.connect(i72);
- boost::signals2::connection c62 = s0.connect(i62);
- boost::signals2::connection c42 = s0.connect(i42);
- const boost::signals2::signal<int (), max_or_default<int> >& cs0 = s0;
- BOOST_CHECK(cs0() == 72);
- }
- {
- make_increasing_int<7> i7;
- make_increasing_int<10> i10;
- boost::signals2::signal<int (), max_or_default<int> > s0;
- boost::signals2::connection c7 = s0.connect(i7);
- boost::signals2::connection c10 = s0.connect(i10);
- BOOST_CHECK(s0() == 10);
- BOOST_CHECK(s0() == 11);
- }
- }
- static void
- test_one_arg()
- {
- boost::signals2::signal<int (int value), max_or_default<int> > s1;
- s1.connect(std::negate<int>());
- s1.connect(boost::bind(std::multiplies<int>(), 2, _1));
- BOOST_CHECK(s1(1) == 2);
- BOOST_CHECK(s1(-1) == 1);
- }
- static void
- test_signal_signal_connect()
- {
- typedef boost::signals2::signal<int (int value), max_or_default<int> > signal_type;
- signal_type s1;
- s1.connect(std::negate<int>());
- BOOST_CHECK(s1(3) == -3);
- {
- signal_type s2;
- s1.connect(s2);
- s2.connect(boost::bind(std::multiplies<int>(), 2, _1));
- s2.connect(boost::bind(std::multiplies<int>(), -3, _1));
- BOOST_CHECK(s2(-3) == 9);
- BOOST_CHECK(s1(3) == 6);
- } // s2 goes out of scope and disconnects
- BOOST_CHECK(s1(3) == -3);
- }
- template<typename ResultType>
- ResultType disconnecting_slot(const boost::signals2::connection &conn, int)
- {
- conn.disconnect();
- return ResultType();
- }
- #ifdef BOOST_NO_VOID_RETURNS
- template<>
- void disconnecting_slot<void>(const boost::signals2::connection &conn, int)
- {
- conn.disconnect();
- return;
- }
- #endif
- template<typename ResultType>
- void test_extended_slot()
- {
- {
- typedef boost::signals2::signal<ResultType (int)> signal_type;
- typedef typename signal_type::extended_slot_type slot_type;
- signal_type sig;
- // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
- ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
- slot_type myslot(fp);
- sig.connect_extended(myslot);
- BOOST_CHECK(sig.num_slots() == 1);
- sig(0);
- BOOST_CHECK(sig.num_slots() == 0);
- }
- { // test 0 arg signal
- typedef boost::signals2::signal<ResultType ()> signal_type;
- typedef typename signal_type::extended_slot_type slot_type;
- signal_type sig;
- // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
- ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
- slot_type myslot(fp, _1, 0);
- sig.connect_extended(myslot);
- BOOST_CHECK(sig.num_slots() == 1);
- sig();
- BOOST_CHECK(sig.num_slots() == 0);
- }
- // test disconnection by slot
- {
- typedef boost::signals2::signal<ResultType (int)> signal_type;
- typedef typename signal_type::extended_slot_type slot_type;
- signal_type sig;
- // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
- ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
- slot_type myslot(fp);
- sig.connect_extended(myslot);
- BOOST_CHECK(sig.num_slots() == 1);
- sig.disconnect(fp);
- BOOST_CHECK(sig.num_slots() == 0);
- }
- }
- void increment_arg(int &value)
- {
- ++value;
- }
- static void
- test_reference_args()
- {
- typedef boost::signals2::signal<void (int &)> signal_type;
- signal_type s1;
- s1.connect(&increment_arg);
- int value = 0;
- s1(value);
- BOOST_CHECK(value == 1);
- }
- static void
- test_typedefs_etc()
- {
- typedef boost::signals2::signal<int (double, long)> signal_type;
- typedef signal_type::slot_type slot_type;
- BOOST_CHECK(typeid(signal_type::slot_result_type) == typeid(int));
- BOOST_CHECK(typeid(signal_type::result_type) == typeid(boost::optional<int>));
- BOOST_CHECK(typeid(signal_type::arg<0>::type) == typeid(double));
- BOOST_CHECK(typeid(signal_type::arg<1>::type) == typeid(long));
- BOOST_CHECK(typeid(signal_type::arg<0>::type) == typeid(signal_type::first_argument_type));
- BOOST_CHECK(typeid(signal_type::arg<1>::type) == typeid(signal_type::second_argument_type));
- BOOST_CHECK(typeid(signal_type::signature_type) == typeid(int (double, long)));
- BOOST_CHECK(signal_type::arity == 2);
- BOOST_CHECK(typeid(slot_type::result_type) == typeid(signal_type::slot_result_type));
- BOOST_CHECK(typeid(slot_type::arg<0>::type) == typeid(signal_type::arg<0>::type));
- BOOST_CHECK(typeid(slot_type::arg<1>::type) == typeid(signal_type::arg<1>::type));
- BOOST_CHECK(typeid(slot_type::arg<0>::type) == typeid(slot_type::first_argument_type));
- BOOST_CHECK(typeid(slot_type::arg<1>::type) == typeid(slot_type::second_argument_type));
- BOOST_CHECK(typeid(slot_type::signature_type) == typeid(signal_type::signature_type));
- BOOST_CHECK(slot_type::arity == signal_type::arity);
- typedef boost::signals2::signal<void (short)> unary_signal_type;
- BOOST_CHECK(typeid(unary_signal_type::slot_result_type) == typeid(void));
- BOOST_CHECK(typeid(unary_signal_type::argument_type) == typeid(short));
- BOOST_CHECK(typeid(unary_signal_type::slot_type::argument_type) == typeid(short));
- }
- class dummy_combiner
- {
- public:
- typedef int result_type;
- dummy_combiner(result_type return_value): _return_value(return_value)
- {}
- template<typename SlotIterator>
- result_type operator()(SlotIterator, SlotIterator)
- {
- return _return_value;
- }
- private:
- result_type _return_value;
- };
- static void
- test_set_combiner()
- {
- typedef boost::signals2::signal<int (), dummy_combiner> signal_type;
- signal_type sig(dummy_combiner(0));
- BOOST_CHECK(sig() == 0);
- BOOST_CHECK(sig.combiner()(0,0) == 0);
- sig.set_combiner(dummy_combiner(1));
- BOOST_CHECK(sig() == 1);
- BOOST_CHECK(sig.combiner()(0,0) == 1);
- }
- static void
- test_swap()
- {
- typedef boost::signals2::signal<int (), dummy_combiner> signal_type;
- signal_type sig1(dummy_combiner(1));
- BOOST_CHECK(sig1() == 1);
- signal_type sig2(dummy_combiner(2));
- BOOST_CHECK(sig2() == 2);
- sig1.swap(sig2);
- BOOST_CHECK(sig1() == 2);
- BOOST_CHECK(sig2() == 1);
- using std::swap;
- swap(sig1, sig2);
- BOOST_CHECK(sig1() == 1);
- BOOST_CHECK(sig2() == 2);
- }
- void test_move()
- {
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- typedef boost::signals2::signal<int (), dummy_combiner> signal_type;
- signal_type sig1(dummy_combiner(1));
- BOOST_CHECK(sig1() == 1);
- signal_type sig2(dummy_combiner(2));
- BOOST_CHECK(sig2() == 2);
- sig1 = std::move(sig2);
- BOOST_CHECK(sig1() == 2);
- signal_type sig3(std::move(sig1));
- BOOST_CHECK(sig3() == 2);
- #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- }
- int
- test_main(int, char* [])
- {
- test_zero_args();
- test_one_arg();
- test_signal_signal_connect();
- test_extended_slot<void>();
- test_extended_slot<int>();
- test_reference_args();
- test_typedefs_etc();
- test_set_combiner();
- test_swap();
- test_move();
- return 0;
- }
|