]> git.lyx.org Git - lyx.git/blob - boost/boost/function/function_template.hpp
update boost
[lyx.git] / boost / boost / function / function_template.hpp
1 // Boost.Function 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 // Note: this header is a header template and must NOT have multiple-inclusion
17 // protection.
18
19 #ifndef BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP
20 #define BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP
21 #  include <cassert>
22 #  include <algorithm>
23 #  include <boost/config.hpp>
24 #  include <boost/function/function_base.hpp>
25 #  include <boost/mem_fn.hpp>
26 #endif // BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP
27
28 // Type of the default allocator
29 #ifndef BOOST_NO_STD_ALLOCATOR
30 #  define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base>
31 #else
32 #  define BOOST_FUNCTION_DEFAULT_ALLOCATOR int
33 #endif // BOOST_NO_STD_ALLOCATOR
34
35 // Comma if nonzero number of arguments
36 #if BOOST_FUNCTION_NUM_ARGS == 0
37 #  define BOOST_FUNCTION_COMMA
38 #else
39 #  define BOOST_FUNCTION_COMMA ,
40 #endif // BOOST_FUNCTION_NUM_ARGS > 0
41
42 // Class names used in this version of the code
43 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
44 #define BOOST_FUNCTION_FUNCTION_INVOKER \
45   BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
46 #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
47   BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
48 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
49   BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
50 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
51   BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
52 #define BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER \
53   BOOST_JOIN(stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
54 #define BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER \
55   BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
56 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
57   BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
58 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
59   BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
60 #define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \
61   BOOST_JOIN(get_stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
62
63 namespace boost {
64   namespace detail {
65     namespace function {
66       template<
67         typename FunctionPtr,
68         typename R BOOST_FUNCTION_COMMA
69         BOOST_FUNCTION_TEMPLATE_PARMS
70         >
71       struct BOOST_FUNCTION_FUNCTION_INVOKER
72       {
73         static R invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
74                         BOOST_FUNCTION_PARMS)
75         {
76           FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
77           return f(BOOST_FUNCTION_ARGS);
78         }
79       };
80
81       template<
82         typename FunctionPtr,
83         typename R BOOST_FUNCTION_COMMA
84         BOOST_FUNCTION_TEMPLATE_PARMS
85         >
86       struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
87       {
88         static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
89                                BOOST_FUNCTION_PARMS)
90
91         {
92           FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
93           f(BOOST_FUNCTION_ARGS);
94           return unusable();
95         }
96       };
97
98       template<
99         typename FunctionObj,
100         typename R BOOST_FUNCTION_COMMA
101         BOOST_FUNCTION_TEMPLATE_PARMS
102       >
103       struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
104       {
105         static R invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA
106                         BOOST_FUNCTION_PARMS)
107
108         {
109           FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
110           return (*f)(BOOST_FUNCTION_ARGS);
111         }
112       };
113
114       template<
115         typename FunctionObj,
116         typename R BOOST_FUNCTION_COMMA
117         BOOST_FUNCTION_TEMPLATE_PARMS
118       >
119       struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
120       {
121         static unusable invoke(any_pointer function_obj_ptr
122                                BOOST_FUNCTION_COMMA
123                                BOOST_FUNCTION_PARMS)
124
125         {
126           FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
127           (*f)(BOOST_FUNCTION_ARGS);
128           return unusable();
129         }
130       };
131
132       template<
133         typename FunctionObj,
134         typename R BOOST_FUNCTION_COMMA
135         BOOST_FUNCTION_TEMPLATE_PARMS
136       >
137       struct BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
138       {
139         static R invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
140         {
141           FunctionObj f = FunctionObj();
142           return f(BOOST_FUNCTION_ARGS);
143         }
144       };
145
146       template<
147         typename FunctionObj,
148         typename R BOOST_FUNCTION_COMMA
149         BOOST_FUNCTION_TEMPLATE_PARMS
150       >
151       struct BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
152       {
153         static unusable invoke(any_pointer BOOST_FUNCTION_COMMA
154                                BOOST_FUNCTION_PARMS)
155
156         {
157           FunctionObj f = FunctionObj();
158           f(BOOST_FUNCTION_ARGS);
159           return unusable();
160         }
161       };
162
163       template<
164         typename FunctionPtr,
165         typename R BOOST_FUNCTION_COMMA
166         BOOST_FUNCTION_TEMPLATE_PARMS
167       >
168       struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
169       {
170         typedef typename ct_if<(is_void<R>::value),
171                             BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
172                             FunctionPtr,
173                             R BOOST_FUNCTION_COMMA
174                             BOOST_FUNCTION_TEMPLATE_ARGS
175                           >,
176                           BOOST_FUNCTION_FUNCTION_INVOKER<
177                             FunctionPtr,
178                             R BOOST_FUNCTION_COMMA
179                             BOOST_FUNCTION_TEMPLATE_ARGS
180                           >
181                        >::type type;
182       };
183
184       template<
185         typename FunctionObj,
186         typename R BOOST_FUNCTION_COMMA
187         BOOST_FUNCTION_TEMPLATE_PARMS
188        >
189       struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
190       {
191         typedef typename ct_if<(is_void<R>::value),
192                             BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
193                             FunctionObj,
194                             R BOOST_FUNCTION_COMMA
195                             BOOST_FUNCTION_TEMPLATE_ARGS
196                           >,
197                           BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
198                             FunctionObj,
199                             R BOOST_FUNCTION_COMMA
200                             BOOST_FUNCTION_TEMPLATE_ARGS
201                           >
202                        >::type type;
203       };
204
205       template<
206         typename FunctionObj,
207         typename R BOOST_FUNCTION_COMMA
208         BOOST_FUNCTION_TEMPLATE_PARMS
209        >
210       struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
211       {
212         typedef typename ct_if<(is_void<R>::value),
213                             BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER<
214                             FunctionObj,
215                             R BOOST_FUNCTION_COMMA
216                             BOOST_FUNCTION_TEMPLATE_ARGS
217                           >,
218                           BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER<
219                             FunctionObj,
220                             R BOOST_FUNCTION_COMMA
221                             BOOST_FUNCTION_TEMPLATE_ARGS
222                           >
223                        >::type type;
224       };
225
226     } // end namespace function
227   } // end namespace detail
228
229   template<
230     typename R BOOST_FUNCTION_COMMA
231     BOOST_FUNCTION_TEMPLATE_PARMS,
232     typename Policy    = empty_function_policy,
233     typename Mixin     = empty_function_mixin,
234     typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
235   >
236   class BOOST_FUNCTION_FUNCTION : public function_base, public Mixin
237   {
238     typedef typename detail::function::function_return_type<R>::type
239       internal_result_type;
240
241   public:
242     BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
243
244 #if BOOST_FUNCTION_NUM_ARGS == 1
245     typedef T0 argument_type;
246 #elif BOOST_FUNCTION_NUM_ARGS == 2
247     typedef T0 first_argument_type;
248     typedef T1 second_argument_type;
249 #endif
250
251 #ifndef BOOST_NO_VOID_RETURNS
252     typedef R         result_type;
253 #else
254     typedef internal_result_type result_type;
255 #endif // BOOST_NO_VOID_RETURNS
256     typedef Policy    policy_type;
257     typedef Mixin     mixin_type;
258     typedef Allocator allocator_type;
259     typedef BOOST_FUNCTION_FUNCTION self_type;
260
261     BOOST_FUNCTION_FUNCTION() : function_base(), Mixin(), invoker(0) {}
262
263     explicit BOOST_FUNCTION_FUNCTION(const Mixin& m) :
264       function_base(), Mixin(m), invoker(0)
265     {
266     }
267
268     // MSVC chokes if the following two constructors are collapsed into
269     // one with a default parameter.
270     template<typename Functor>
271     BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) :
272       function_base(), Mixin(), invoker(0)
273     {
274       this->assign_to(f);
275     }
276
277     template<typename Functor>
278     BOOST_FUNCTION_FUNCTION(Functor f, const Mixin& m) :
279       function_base(), Mixin(m), invoker(0)
280     {
281       this->assign_to(f);
282     }
283
284     BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
285       function_base(), Mixin(static_cast<const Mixin&>(f)), invoker(0)
286     {
287       this->assign_to_own(f);
288     }
289
290     ~BOOST_FUNCTION_FUNCTION() { clear(); }
291
292     result_type operator()(BOOST_FUNCTION_PARMS) const
293     {
294       assert(!this->empty());
295
296       policy_type policy;
297       policy.precall(this);
298
299       internal_result_type result = invoker(function_base::functor
300                                             BOOST_FUNCTION_COMMA
301                                             BOOST_FUNCTION_ARGS);
302
303       policy.postcall(this);
304 #ifndef BOOST_NO_VOID_RETURNS
305       return static_cast<result_type>(result);
306 #else
307       return result;
308 #endif // BOOST_NO_VOID_RETURNS
309     }
310
311     // The distinction between when to use BOOST_FUNCTION_FUNCTION and
312     // when to use self_type is obnoxious. MSVC cannot handle self_type as
313     // the return type of these assignment operators, but Borland C++ cannot
314     // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
315     // construct.
316     template<typename Functor>
317     BOOST_FUNCTION_FUNCTION&
318     operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
319     {
320       self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
321       return *this;
322     }
323
324     template<typename Functor>
325     void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
326     {
327       int deprecated;
328       self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
329     }
330
331     // Assignment from another BOOST_FUNCTION_FUNCTION
332     BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
333     {
334       if (&f == this)
335         return *this;
336
337       self_type(f).swap(*this);
338       return *this;
339     }
340
341     // Assignment from another BOOST_FUNCTION_FUNCTION
342     void set(const BOOST_FUNCTION_FUNCTION& f)
343     {
344       //int deprecated;
345       if (&f == this)
346         return;
347
348       self_type(f).swap(*this);
349     }
350
351     void swap(BOOST_FUNCTION_FUNCTION& other)
352     {
353       if (&other == this)
354         return;
355
356       std::swap(function_base::manager, other.manager);
357       std::swap(function_base::functor, other.functor);
358       std::swap(invoker, other.invoker);
359       std::swap(static_cast<Mixin&>(*this), static_cast<Mixin&>(other));
360     }
361
362     // Clear out a target, if there is one
363     void clear()
364     {
365       if (function_base::manager) {
366         function_base::functor =
367           function_base::manager(function_base::functor,
368                                  detail::function::destroy_functor_tag);
369       }
370
371       function_base::manager = 0;
372       invoker = 0;
373     }
374
375   private:
376     void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
377     {
378       if (!f.empty()) {
379         invoker = f.invoker;
380         function_base::manager = f.manager;
381         function_base::functor =
382           f.manager(f.functor, detail::function::clone_functor_tag);
383       }
384     }
385
386     template<typename Functor>
387     void assign_to(Functor f)
388     {
389       typedef typename detail::function::get_function_tag<Functor>::type tag;
390       this->assign_to(f, tag());
391     }
392
393     template<typename FunctionPtr>
394     void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
395     {
396       clear();
397
398       if (f) {
399         typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
400                            FunctionPtr,
401                            R BOOST_FUNCTION_COMMA
402                            BOOST_FUNCTION_TEMPLATE_ARGS
403                          >::type
404           invoker_type;
405
406         invoker = &invoker_type::invoke;
407         function_base::manager =
408           &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
409         function_base::functor =
410           function_base::manager(detail::function::any_pointer(
411                             // should be a reinterpret cast, but some compilers
412                             // insist on giving cv-qualifiers to free functions
413                             (void (*)())(f)
414                           ),
415                           detail::function::clone_functor_tag);
416       }
417     }
418
419 #if BOOST_FUNCTION_NUM_ARGS > 0
420     template<typename MemberPtr>
421     void assign_to(MemberPtr f, detail::function::member_ptr_tag)
422     {
423       this->assign_to(mem_fn(f));
424     }
425 #endif // BOOST_FUNCTION_NUM_ARGS > 0
426
427     template<typename FunctionObj>
428     void assign_to(FunctionObj f, detail::function::function_obj_tag)
429     {
430       if (!detail::function::has_empty_target(addressof(f))) {
431         typedef
432           typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
433                                        FunctionObj,
434                                        R BOOST_FUNCTION_COMMA
435                                        BOOST_FUNCTION_TEMPLATE_ARGS
436                                      >::type
437           invoker_type;
438
439         invoker = &invoker_type::invoke;
440         function_base::manager = &detail::function::functor_manager<
441                                     FunctionObj, Allocator>::manage;
442 #ifndef BOOST_NO_STD_ALLOCATOR
443         typedef typename Allocator::template rebind<FunctionObj>::other
444           allocator_type;
445         typedef typename allocator_type::pointer pointer_type;
446         allocator_type allocator;
447         pointer_type copy = allocator.allocate(1);
448         allocator.construct(copy, f);
449
450         // Get back to the original pointer type
451         FunctionObj* new_f = static_cast<FunctionObj*>(copy);
452 #else
453         FunctionObj* new_f = new FunctionObj(f);
454 #endif // BOOST_NO_STD_ALLOCATOR
455         function_base::functor =
456           detail::function::any_pointer(static_cast<void*>(new_f));
457       }
458     }
459
460     template<typename FunctionObj>
461     void assign_to(const reference_wrapper<FunctionObj>& f,
462                    detail::function::function_obj_ref_tag)
463     {
464       if (!detail::function::has_empty_target(f.get_pointer())) {
465         typedef
466           typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
467                                        FunctionObj,
468                                        R BOOST_FUNCTION_COMMA
469                                        BOOST_FUNCTION_TEMPLATE_ARGS
470                                      >::type
471           invoker_type;
472
473         invoker = &invoker_type::invoke;
474         function_base::manager = &detail::function::trivial_manager;
475         function_base::functor =
476           function_base::manager(
477             detail::function::any_pointer(
478               const_cast<FunctionObj*>(f.get_pointer())),
479             detail::function::clone_functor_tag);
480       }
481     }
482
483     template<typename FunctionObj>
484     void assign_to(FunctionObj, detail::function::stateless_function_obj_tag)
485     {
486       typedef
487           typename detail::function::
488                      BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
489                        FunctionObj,
490                        R BOOST_FUNCTION_COMMA
491                        BOOST_FUNCTION_TEMPLATE_ARGS
492                      >::type
493           invoker_type;
494       invoker = &invoker_type::invoke;
495       function_base::manager = &detail::function::trivial_manager;
496       function_base::functor = detail::function::any_pointer(this);
497     }
498
499     typedef internal_result_type (*invoker_type)(detail::function::any_pointer
500                                                  BOOST_FUNCTION_COMMA
501                                                  BOOST_FUNCTION_TEMPLATE_ARGS);
502
503     invoker_type invoker;
504   };
505
506   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
507            typename Policy, typename Mixin, typename Allocator>
508   inline void swap(BOOST_FUNCTION_FUNCTION<
509                      R BOOST_FUNCTION_COMMA
510                      BOOST_FUNCTION_TEMPLATE_ARGS ,
511                      Policy,
512                      Mixin,
513                      Allocator
514                    >& f1,
515                    BOOST_FUNCTION_FUNCTION<
516                      R BOOST_FUNCTION_COMMA
517                      BOOST_FUNCTION_TEMPLATE_ARGS,
518                      Policy,
519                      Mixin,
520                      Allocator
521                    >& f2)
522   {
523     f1.swap(f2);
524   }
525 }
526
527 // Cleanup after ourselves...
528 #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
529 #undef BOOST_FUNCTION_COMMA
530 #undef BOOST_FUNCTION_FUNCTION
531 #undef BOOST_FUNCTION_FUNCTION_INVOKER
532 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
533 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
534 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
535 #undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
536 #undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
537 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
538 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
539 #undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
540 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER