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