]> git.lyx.org Git - lyx.git/blob - boost/boost/signals/signal_template.hpp
major boost update
[lyx.git] / boost / boost / signals / signal_template.hpp
1 // Boost.Signals library
2 //
3 // Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
4 //
5 // Permission to copy, use, sell and distribute this software is granted
6 // provided this copyright notice appears in all copies.
7 // Permission to modify the code and to distribute modified code is granted
8 // provided this copyright notice appears in all copies, and a notice
9 // that the code was modified is included with the copyright notice.
10 //
11 // This software is provided "as is" without express or implied warranty,
12 // and with no claim as to its suitability for any purpose.
13  
14 // For more information, see http://www.boost.org
15
16 // This file intentionally does not have include guards, because it is meant
17 // to be included multiple times (one for each signalN class). The 
18 // BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED macro merely serves to
19 // suppress reinclusion of the files that this header depends on.
20 #ifndef BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
21 #define BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
22 #  include <boost/config.hpp>
23 #  include <boost/signals/connection.hpp>
24 #  include <boost/utility.hpp>
25 #  include <boost/ref.hpp>
26 #  include <boost/signals/slot.hpp>
27 #  include <boost/last_value.hpp>
28 #  include <boost/signals/detail/signal_base.hpp>
29 #  include <boost/signals/detail/slot_call_iterator.hpp>
30 #  include <cassert>
31 #  include <functional>
32 #  include <memory>
33 #  include <string>
34 #endif // !BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
35
36 // Include the appropriate functionN header
37 #define BOOST_SIGNAL_FUNCTION_N_HEADER BOOST_JOIN(<boost/function/function,BOOST_SIGNALS_NUM_ARGS.hpp>)
38 #include BOOST_SIGNAL_FUNCTION_N_HEADER
39
40 // Determine if a comma should follow a listing of the arguments/parameters
41 #if BOOST_SIGNALS_NUM_ARGS == 0
42 #  define BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
43 #else
44 #  define BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS ,
45 #endif // BOOST_SIGNALS_NUM_ARGS > 0
46
47 // Define class names used
48 #define BOOST_SIGNALS_SIGNAL BOOST_JOIN(signal,BOOST_SIGNALS_NUM_ARGS)
49 #define BOOST_SIGNALS_FUNCTION BOOST_JOIN(function,BOOST_SIGNALS_NUM_ARGS)
50 #define BOOST_SIGNALS_ARGS_STRUCT BOOST_JOIN(args,BOOST_SIGNALS_NUM_ARGS)
51 #define BOOST_SIGNALS_CALL_BOUND BOOST_JOIN(call_bound,BOOST_SIGNALS_NUM_ARGS)
52
53 // Define commonly-used instantiations
54 #define BOOST_SIGNALS_ARGS_STRUCT_INST \
55   signals::detail::BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>
56
57 namespace boost {
58   namespace signals {
59     namespace detail {
60       // Holds the arguments for a bound slot call in a single place
61       template<BOOST_SIGNALS_TEMPLATE_PARMS
62                BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
63                typename Dummy = int>
64       struct BOOST_SIGNALS_ARGS_STRUCT {
65         BOOST_SIGNALS_ARGS_STRUCT(BOOST_SIGNALS_COPY_PARMS)
66           BOOST_SIGNALS_INIT_ARGS
67         {
68         }
69
70         BOOST_SIGNALS_ARGS_AS_MEMBERS
71       };
72
73       // Function object that calls the function object given to it, passing
74       // the bound arguments along to that underlying function object
75       template<typename R>
76       struct BOOST_SIGNALS_CALL_BOUND {
77         template<BOOST_SIGNALS_TEMPLATE_PARMS
78                  BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
79                  typename F>
80         struct caller {
81           typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
82             args_type;
83
84           args_type args;
85
86           typedef R result_type;
87
88           caller() {}
89           caller(args_type a) : args(a) {}
90
91           template<typename Pair>
92           R operator()(const Pair& slot) const
93           {
94             F* target = const_cast<F*>(any_cast<F>(&slot.second.second));
95             return (*target)(BOOST_SIGNALS_BOUND_ARGS);
96           }
97         };
98       };
99
100       template<>
101       struct BOOST_SIGNALS_CALL_BOUND<void> {
102         template<BOOST_SIGNALS_TEMPLATE_PARMS
103                  BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
104                  typename F>
105         struct caller {
106           typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
107             args_type;
108
109           args_type args;
110
111           typedef unusable result_type;
112
113           caller(args_type a) : args(a) {}
114
115           template<typename Pair>
116           unusable operator()(const Pair& slot) const
117           {
118             F* target = const_cast<F*>(any_cast<F>(&slot.second.second));
119             (*target)(BOOST_SIGNALS_BOUND_ARGS);
120             return unusable();
121           }
122         };
123       };
124     } // namespace detail
125   } // namespace signals
126
127   // The actual signalN class
128   template<
129     typename R,
130     BOOST_SIGNALS_TEMPLATE_PARMS 
131     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
132     typename Combiner = last_value<R>,
133     typename Group = int,
134     typename GroupCompare = std::less<Group>,
135     typename SlotFunction = BOOST_SIGNALS_FUNCTION<
136                               R BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
137                               BOOST_SIGNALS_TEMPLATE_ARGS> 
138   >
139   class BOOST_SIGNALS_SIGNAL : 
140     public signals::detail::signal_base, // management of slot list
141     public signals::trackable // signals are trackable
142   {
143   public:
144     // The slot function type
145     typedef SlotFunction slot_function_type;
146
147     // Result type of a slot
148     typedef typename signals::detail::slot_result_type<R>::type
149       slot_result_type;
150
151     // Argument types
152     BOOST_SIGNALS_ARG_TYPES
153
154 #if BOOST_SIGNALS_NUM_ARGS == 1
155     typedef T1 argument_type;
156 #elif BOOST_SIGNALS_NUM_ARGS == 2
157     typedef T1 first_argument_type;
158     typedef T2 second_argument_type;
159 #endif
160
161   private:
162     // The real slot name comparison object type
163     typedef signals::detail::any_bridge_compare<GroupCompare, Group>
164       real_group_compare_type;
165
166     // The function object passed to the slot call iterator that will call
167     // the underlying slot function with its arguments bound
168     typedef signals::detail::BOOST_SIGNALS_CALL_BOUND<R> 
169       outer_bound_slot_caller;
170     typedef typename outer_bound_slot_caller::template
171               caller<BOOST_SIGNALS_TEMPLATE_ARGS
172                      BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
173                      slot_function_type>
174       call_bound_slot;
175
176   public:
177     // Combiner's result type
178     typedef typename Combiner::result_type result_type; 
179
180     // Combiner type
181     typedef Combiner combiner_type;
182
183     // Slot type
184     typedef slot<slot_function_type> slot_type;
185
186     // Slot name type and comparison
187     typedef Group group_type;
188     typedef GroupCompare group_compare_type;
189
190     typedef typename signals::detail::slot_call_iterator_generator<
191                        call_bound_slot, 
192                        slot_iterator>::type slot_call_iterator;
193
194     explicit 
195     BOOST_SIGNALS_SIGNAL(const Combiner& c = Combiner(),
196                          const GroupCompare& comp = GroupCompare()) : 
197       signals::detail::signal_base(real_group_compare_type(comp)),
198       combiner(c)
199     {
200     }
201
202     // Connect a slot to this signal
203     signals::connection connect(const slot_type&);
204     signals::connection connect(const group_type&, const slot_type&);
205
206     // Disconnect a named slot
207     void disconnect(const group_type& group)
208     {
209       impl->disconnect(group);
210     }
211
212     // Emit the signal
213     result_type operator()(BOOST_SIGNALS_PARMS);
214     result_type operator()(BOOST_SIGNALS_PARMS) const;
215
216   private:
217     Combiner combiner;
218   };
219
220   template<
221     typename R,
222     BOOST_SIGNALS_TEMPLATE_PARMS
223     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
224     typename Combiner,
225     typename Group,
226     typename GroupCompare,
227     typename SlotFunction
228   >
229   signals::connection 
230   BOOST_SIGNALS_SIGNAL<                                 
231     R, BOOST_SIGNALS_TEMPLATE_ARGS                      
232     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS  
233     Combiner, Group, GroupCompare, SlotFunction
234   >::connect(const slot_type& in_slot)
235   {
236     // If the slot has been disconnected, just return a disconnected 
237     // connection
238     if (!in_slot.is_active()) {
239       return signals::connection();
240     }
241
242     return impl->connect_slot(in_slot.get_slot_function(),
243                               any(),
244                               in_slot.get_bound_objects());
245   }
246
247   template<
248     typename R,
249     BOOST_SIGNALS_TEMPLATE_PARMS
250     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
251     typename Combiner,
252     typename Group,
253     typename GroupCompare,
254     typename SlotFunction
255   >
256   signals::connection 
257   BOOST_SIGNALS_SIGNAL<                                 
258     R, BOOST_SIGNALS_TEMPLATE_ARGS                      
259     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS  
260     Combiner, Group, GroupCompare, SlotFunction
261   >::connect(const group_type& group, 
262              const slot_type& in_slot)
263   {
264     return impl->connect_slot(in_slot.get_slot_function(),
265                               group,
266                               in_slot.get_bound_objects());
267   }
268
269   template<
270     typename R,
271     BOOST_SIGNALS_TEMPLATE_PARMS
272     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
273     typename Combiner,
274     typename Group,
275     typename GroupCompare,
276     typename SlotFunction
277   >                                                          
278   typename BOOST_SIGNALS_SIGNAL<                                 
279              R, BOOST_SIGNALS_TEMPLATE_ARGS                      
280              BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS  
281              Combiner, Group, GroupCompare, SlotFunction>::result_type
282   BOOST_SIGNALS_SIGNAL<                                 
283     R, BOOST_SIGNALS_TEMPLATE_ARGS                      
284     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS  
285     Combiner, Group, GroupCompare, SlotFunction
286   >::operator()(BOOST_SIGNALS_PARMS)
287   {
288     // Notify the slot handling code that we are making a call
289     signals::detail::call_notification notification(this->impl);
290
291     // Construct a function object that will call the underlying slots
292     // with the given arguments. 
293 #if BOOST_SIGNALS_NUM_ARGS == 0
294     BOOST_SIGNALS_ARGS_STRUCT_INST args;
295 #else
296     BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
297 #endif // BOOST_SIGNALS_NUM_ARGS > 0
298     call_bound_slot f(&args);
299
300     // Let the combiner call the slots via a pair of input iterators
301     return combiner(signals::detail::make_slot_call_iterator(
302                       notification.impl->slots.begin(), impl->slots.end(), f),
303                     signals::detail::make_slot_call_iterator(
304                       notification.impl->slots.end(), impl->slots.end(), f));
305   }
306
307   template<
308     typename R,
309     BOOST_SIGNALS_TEMPLATE_PARMS
310     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
311     typename Combiner,
312     typename Group,
313     typename GroupCompare,
314     typename SlotFunction
315   >                                                          
316   typename BOOST_SIGNALS_SIGNAL<                                 
317              R, BOOST_SIGNALS_TEMPLATE_ARGS                      
318              BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS  
319              Combiner, Group, GroupCompare, SlotFunction>::result_type
320   BOOST_SIGNALS_SIGNAL<                                 
321     R, BOOST_SIGNALS_TEMPLATE_ARGS                      
322     BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS  
323     Combiner, Group, GroupCompare, SlotFunction
324   >::operator()(BOOST_SIGNALS_PARMS) const
325   {
326     // Notify the slot handling code that we are making a call
327     signals::detail::call_notification notification(this->impl);
328
329     // Construct a function object that will call the underlying slots
330     // with the given arguments. 
331 #if BOOST_SIGNALS_NUM_ARGS == 0
332     BOOST_SIGNALS_ARGS_STRUCT_INST args;
333 #else
334     BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
335 #endif // BOOST_SIGNALS_NUM_ARGS > 0
336
337     call_bound_slot f(&args);
338
339     // Let the combiner call the slots via a pair of input iterators
340     return combiner(signals::detail::make_slot_call_iterator(
341                       notification.impl->slots.begin(), impl->slots.end(), f),
342                     signals::detail::make_slot_call_iterator(
343                       notification.impl->slots.end(), impl->slots.end(), f));
344   }
345 } // namespace boost
346
347 #undef BOOST_SIGNAL_FUNCTION_N_HEADER
348 #undef BOOST_SIGNALS_ARGS_STRUCT_INST
349 #undef BOOST_SIGNALS_CALL_BOUND
350 #undef BOOST_SIGNALS_ARGS_STRUCT
351 #undef BOOST_SIGNALS_FUNCTION
352 #undef BOOST_SIGNALS_SIGNAL
353 #undef BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS