1 // Boost.Signals2 library 2 3 // Copyright Frank Mori Hess 2007-2008. 4 // Copyright Timmo Stange 2007. 5 // Copyright Douglas Gregor 2001-2004. Use, modification and 6 // distribution is subject to the Boost Software License, Version 7 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 // http://www.boost.org/LICENSE_1_0.txt) 9 10 // For more information, see http://www.boost.org 11 12 // This file is included iteratively, and should not be protected from multiple inclusion 13 14 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES 15 #define BOOST_SIGNALS2_NUM_ARGS BOOST_PP_ITERATION() 16 #else 17 #define BOOST_SIGNALS2_NUM_ARGS 1 18 #endif 19 20 21 namespace boost 22 { 23 namespace signals2 24 { 25 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES 26 template<typename Signature, typename SlotFunction> class slot; 27 #else 28 template<typename Signature, typename SlotFunction = boost::function<Signature> > 29 class slot; 30 31 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1900) 32 template<typename Signature, typename SlotFunction> class slot{}; 33 #endif 34 #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES 35 36 template<BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)> 37 class BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION 38 : public slot_base, public detail::BOOST_SIGNALS2_STD_FUNCTIONAL_BASE(R) 39 40 { 41 public: 42 template<BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS, Other), typename OtherSlotFunction> 43 friend class BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS); 44 45 typedef SlotFunction slot_function_type; 46 typedef R result_type; 47 typedef typename mpl::identity<BOOST_SIGNALS2_SIGNATURE_FUNCTION_TYPE(BOOST_SIGNALS2_NUM_ARGS)>::type signature_type; 48 49 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES 50 51 // typedef Tn argn_type; 52 #define BOOST_SIGNALS2_MISC_STATEMENT(z, n, data) \ 53 typedef BOOST_PP_CAT(T, BOOST_PP_INC(n)) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type); 54 BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_MISC_STATEMENT, ~) 55 #undef BOOST_SIGNALS2_MISC_STATEMENT 56 #if BOOST_SIGNALS2_NUM_ARGS == 1 57 typedef arg1_type argument_type; 58 #elif BOOST_SIGNALS2_NUM_ARGS == 2 59 typedef arg1_type first_argument_type; 60 typedef arg2_type second_argument_type; 61 #endif 62 63 template<unsigned n> class arg : public 64 detail::BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) 65 <n BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS) 66 BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS)> 67 {}; 68 69 BOOST_STATIC_CONSTANT(int, arity = BOOST_SIGNALS2_NUM_ARGS); 70 71 #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES 72 73 template<unsigned n> class arg 74 { 75 public: 76 typedef typename detail::variadic_arg_type<n, Args...>::type type; 77 }; 78 BOOST_STATIC_CONSTANT(int, arity = sizeof...(Args)); 79 80 #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES 81 82 template<typename F> 83 BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const F& f) 84 { 85 init_slot_function(f); 86 } 87 // copy constructors 88 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES 89 template<BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS, Other), typename OtherSlotFunction> 90 BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) 91 <BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS, Other), OtherSlotFunction> &other_slot): 92 slot_base(other_slot), _slot_function(other_slot._slot_function) 93 { 94 } 95 #endif 96 template<typename Signature, typename OtherSlotFunction> 97 BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const slot<Signature, OtherSlotFunction> &other_slot): 98 slot_base(other_slot), _slot_function(other_slot._slot_function) 99 { 100 } 101 // bind syntactic sugar 102 BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTORS 103 // invocation 104 R operator()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) 105 { 106 locked_container_type locked_objects = lock(); 107 return _slot_function(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS)); 108 } 109 R operator()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const 110 { 111 locked_container_type locked_objects = lock(); 112 return _slot_function(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS)); 113 } 114 // tracking 115 BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track(const weak_ptr<void> &tracked) { 116 _tracked_objects.push_back(tracked); 117 return *this; 118 } 119 BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track(const signal_base &signal) 120 { 121 track_signal(signal); 122 return *this; 123 } 124 BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track(const slot_base &slot) 125 { 126 tracked_container_type::const_iterator it; 127 for(it = slot.tracked_objects().begin(); it != slot.tracked_objects().end(); ++it) 128 { 129 _tracked_objects.push_back(*it); 130 } 131 return *this; 132 } 133 template<typename ForeignWeakPtr> 134 BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track_foreign(const ForeignWeakPtr &tracked, 135 typename weak_ptr_traits<ForeignWeakPtr>::shared_type * /*SFINAE*/ = 0) 136 { 137 _tracked_objects.push_back(detail::foreign_void_weak_ptr(tracked)); 138 return *this; 139 } 140 template<typename ForeignSharedPtr> 141 BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track_foreign(const ForeignSharedPtr &tracked, 142 typename shared_ptr_traits<ForeignSharedPtr>::weak_type * /*SFINAE*/ = 0) 143 { 144 _tracked_objects.push_back 145 ( 146 detail::foreign_void_weak_ptr 147 ( 148 typename shared_ptr_traits<ForeignSharedPtr>::weak_type(tracked) 149 ) 150 ); 151 return *this; 152 } 153 154 const slot_function_type& slot_function() const {return _slot_function;} 155 slot_function_type& slot_function() {return _slot_function;} 156 private: 157 template<typename F> 158 void init_slot_function(const F& f) 159 { 160 _slot_function = detail::get_invocable_slot(f, detail::tag_type(f)); 161 signals2::detail::tracked_objects_visitor visitor(this); 162 boost::visit_each(visitor, f); 163 } 164 165 SlotFunction _slot_function; 166 }; 167 168 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES 169 namespace detail 170 { 171 template<unsigned arity, typename Signature, typename SlotFunction> 172 class slotN; 173 // partial template specialization 174 template<typename Signature, typename SlotFunction> 175 class slotN<BOOST_SIGNALS2_NUM_ARGS, Signature, SlotFunction> 176 { 177 public: 178 typedef BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)< 179 BOOST_SIGNALS2_PORTABLE_SIGNATURE(BOOST_SIGNALS2_NUM_ARGS, Signature), 180 SlotFunction> type; 181 }; 182 } 183 #endif 184 } // end namespace signals2 185 } // end namespace boost 186 187 #undef BOOST_SIGNALS2_NUM_ARGS 188