18
18
#include < typeinfo>
19
19
#include < boost/config.hpp>
20
20
#include < boost/assert.hpp>
21
+ #include < boost/type_traits/is_const.hpp>
21
22
#include < boost/type_traits/is_integral.hpp>
23
+ #include < boost/type_traits/is_volatile.hpp>
22
24
#include < boost/type_traits/composite_traits.hpp>
25
+ #include < boost/type_traits/ice.hpp>
23
26
#include < boost/ref.hpp>
24
27
#include < boost/mpl/if.hpp>
25
28
#include < boost/detail/workaround.hpp>
30
33
# include " boost/mpl/bool.hpp"
31
34
#endif
32
35
#include < boost/function_equal.hpp>
36
+ #include < boost/function/function_fwd.hpp>
33
37
34
38
#if defined(BOOST_MSVC)
35
39
# pragma warning( push )
63
67
# define BOOST_FUNCTION_TARGET_FIX (x )
64
68
#endif // not MSVC
65
69
66
- #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
67
- // Work around a compiler bug.
68
- // boost::python::objects::function has to be seen by the compiler before the
69
- // boost::function class template.
70
- namespace boost { namespace python { namespace objects {
71
- class function ;
72
- }}}
73
- #endif
74
-
75
- #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
76
- || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
77
- || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540 )
78
- # define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
79
- #endif
80
-
81
- #if !BOOST_WORKAROUND(__BORLANDC__, < 0x600)
70
+ #if !BOOST_WORKAROUND(__BORLANDC__, < 0x5A0)
82
71
# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL (Functor,Type ) \
83
72
typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
84
73
(::boost::is_integral<Functor>::value)>::value), \
@@ -92,22 +81,6 @@ namespace boost { namespace python { namespace objects {
92
81
Type>::type
93
82
#endif
94
83
95
- #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
96
- namespace boost {
97
-
98
- template <typename Signature>
99
- class function ;
100
-
101
- template <typename Signature>
102
- inline void swap (function<Signature>& f1,
103
- function<Signature>& f2)
104
- {
105
- f1.swap (f2);
106
- }
107
-
108
- } // end namespace boost
109
- #endif // have partial specialization
110
-
111
84
namespace boost {
112
85
namespace detail {
113
86
namespace function {
@@ -122,11 +95,18 @@ namespace boost {
122
95
union function_buffer
123
96
{
124
97
// For pointers to function objects
125
- void * obj_ptr;
98
+ mutable void * obj_ptr;
126
99
127
100
// For pointers to std::type_info objects
128
- // (get_functor_type_tag, check_functor_type_tag).
129
- const void * const_obj_ptr;
101
+ struct type_t {
102
+ // (get_functor_type_tag, check_functor_type_tag).
103
+ const BOOST_FUNCTION_STD_NS::type_info* type;
104
+
105
+ // Whether the type is const-qualified.
106
+ bool const_qualified;
107
+ // Whether the type is volatile-qualified.
108
+ bool volatile_qualified;
109
+ } type;
130
110
131
111
// For function pointers of all kinds
132
112
mutable void (*func_ptr)();
@@ -137,6 +117,14 @@ namespace boost {
137
117
void * obj_ptr;
138
118
} bound_memfunc_ptr;
139
119
120
+ // For references to function objects. We explicitly keep
121
+ // track of the cv-qualifiers on the object referenced.
122
+ struct obj_ref_t {
123
+ mutable void * obj_ptr;
124
+ bool is_const_qualified;
125
+ bool is_volatile_qualified;
126
+ } obj_ref;
127
+
140
128
// To relax aliasing constraints
141
129
mutable char data;
142
130
};
@@ -168,6 +156,7 @@ namespace boost {
168
156
// The operation type to perform on the given functor/function pointer
169
157
enum functor_manager_operation_type {
170
158
clone_functor_tag,
159
+ move_functor_tag,
171
160
destroy_functor_tag,
172
161
check_functor_type_tag,
173
162
get_functor_type_tag
@@ -204,34 +193,45 @@ namespace boost {
204
193
struct reference_manager
205
194
{
206
195
static inline void
207
- get (const function_buffer& in_buffer, function_buffer& out_buffer,
208
- functor_manager_operation_type op)
196
+ manage (const function_buffer& in_buffer, function_buffer& out_buffer,
197
+ functor_manager_operation_type op)
209
198
{
210
199
switch (op) {
211
200
case clone_functor_tag:
212
- out_buffer.obj_ptr = in_buffer.obj_ptr ;
201
+ out_buffer.obj_ref .obj_ptr = in_buffer.obj_ref .obj_ptr ;
202
+ return ;
203
+
204
+ case move_functor_tag:
205
+ out_buffer.obj_ref .obj_ptr = in_buffer.obj_ref .obj_ptr ;
206
+ in_buffer.obj_ref .obj_ptr = 0 ;
213
207
return ;
214
208
215
209
case destroy_functor_tag:
216
- out_buffer.obj_ptr = 0 ;
210
+ out_buffer.obj_ref . obj_ptr = 0 ;
217
211
return ;
218
212
219
213
case check_functor_type_tag:
220
214
{
221
- // DPG TBD: Since we're only storing a pointer, it's
222
- // possible that the user could ask for a base class or
223
- // derived class. Is that okay?
224
- const BOOST_FUNCTION_STD_NS::type_info& check_type =
225
- *static_cast <const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr );
226
- if (BOOST_FUNCTION_COMPARE_TYPE_ID (check_type, typeid (F)))
227
- out_buffer.obj_ptr = in_buffer.obj_ptr ;
215
+ const BOOST_FUNCTION_STD_NS::type_info& check_type
216
+ = *out_buffer.type .type ;
217
+
218
+ // Check whether we have the same type. We can add
219
+ // cv-qualifiers, but we can't take them away.
220
+ if (BOOST_FUNCTION_COMPARE_TYPE_ID (check_type, typeid (F))
221
+ && (!in_buffer.obj_ref .is_const_qualified
222
+ || out_buffer.type .const_qualified )
223
+ && (!in_buffer.obj_ref .is_volatile_qualified
224
+ || out_buffer.type .volatile_qualified ))
225
+ out_buffer.obj_ptr = in_buffer.obj_ref .obj_ptr ;
228
226
else
229
227
out_buffer.obj_ptr = 0 ;
230
228
}
231
229
return ;
232
230
233
231
case get_functor_type_tag:
234
- out_buffer.const_obj_ptr = &typeid (F);
232
+ out_buffer.type .type = &typeid (F);
233
+ out_buffer.type .const_qualified = in_buffer.obj_ref .is_const_qualified ;
234
+ out_buffer.type .volatile_qualified = in_buffer.obj_ref .is_volatile_qualified ;
235
235
return ;
236
236
}
237
237
}
@@ -277,15 +277,22 @@ namespace boost {
277
277
{
278
278
if (op == clone_functor_tag)
279
279
out_buffer.func_ptr = in_buffer.func_ptr ;
280
- else if (op == destroy_functor_tag)
280
+ else if (op == move_functor_tag) {
281
+ out_buffer.func_ptr = in_buffer.func_ptr ;
282
+ in_buffer.func_ptr = 0 ;
283
+ } else if (op == destroy_functor_tag)
281
284
out_buffer.func_ptr = 0 ;
282
- else /* op == check_functor_type_tag */ {
283
- const BOOST_FUNCTION_STD_NS::type_info& check_type =
284
- * static_cast < const BOOST_FUNCTION_STD_NS::type_info*>( out_buffer.const_obj_ptr ) ;
285
+ else if ( op == check_functor_type_tag) {
286
+ const BOOST_FUNCTION_STD_NS::type_info& check_type
287
+ = * out_buffer.type . type ;
285
288
if (BOOST_FUNCTION_COMPARE_TYPE_ID (check_type, typeid (Functor)))
286
289
out_buffer.obj_ptr = &in_buffer.func_ptr ;
287
290
else
288
291
out_buffer.obj_ptr = 0 ;
292
+ } else /* op == get_functor_type_tag */ {
293
+ out_buffer.type .type = &typeid (Functor);
294
+ out_buffer.type .const_qualified = false ;
295
+ out_buffer.type .volatile_qualified = false ;
289
296
}
290
297
}
291
298
@@ -294,20 +301,28 @@ namespace boost {
294
301
manage_small (const function_buffer& in_buffer, function_buffer& out_buffer,
295
302
functor_manager_operation_type op)
296
303
{
297
- if (op == clone_functor_tag) {
304
+ if (op == clone_functor_tag || op == move_functor_tag ) {
298
305
const functor_type* in_functor =
299
306
reinterpret_cast <const functor_type*>(&in_buffer.data );
300
307
new ((void *)&out_buffer.data ) functor_type (*in_functor);
308
+
309
+ if (op == move_functor_tag) {
310
+ reinterpret_cast <functor_type*>(&in_buffer.data )->~Functor ();
311
+ }
301
312
} else if (op == destroy_functor_tag) {
302
313
// Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
303
314
reinterpret_cast <functor_type*>(&out_buffer.data )->~Functor ();
304
- } else /* op == check_functor_type_tag */ {
305
- const BOOST_FUNCTION_STD_NS::type_info& check_type =
306
- * static_cast < const BOOST_FUNCTION_STD_NS::type_info*>( out_buffer.const_obj_ptr ) ;
315
+ } else if ( op == check_functor_type_tag) {
316
+ const BOOST_FUNCTION_STD_NS::type_info& check_type
317
+ = * out_buffer.type . type ;
307
318
if (BOOST_FUNCTION_COMPARE_TYPE_ID (check_type, typeid (Functor)))
308
319
out_buffer.obj_ptr = &in_buffer.data ;
309
320
else
310
321
out_buffer.obj_ptr = 0 ;
322
+ } else /* op == get_functor_type_tag */ {
323
+ out_buffer.type .type = &typeid (Functor);
324
+ out_buffer.type .const_qualified = false ;
325
+ out_buffer.type .volatile_qualified = false ;
311
326
}
312
327
}
313
328
};
@@ -347,19 +362,26 @@ namespace boost {
347
362
(const functor_type*)(in_buffer.obj_ptr );
348
363
functor_type* new_f = new functor_type (*f);
349
364
out_buffer.obj_ptr = new_f;
365
+ } else if (op == move_functor_tag) {
366
+ out_buffer.obj_ptr = in_buffer.obj_ptr ;
367
+ in_buffer.obj_ptr = 0 ;
350
368
} else if (op == destroy_functor_tag) {
351
369
/* Cast from the void pointer to the functor pointer type */
352
370
functor_type* f =
353
371
static_cast <functor_type*>(out_buffer.obj_ptr );
354
372
delete f;
355
373
out_buffer.obj_ptr = 0 ;
356
- } else /* op == check_functor_type_tag */ {
357
- const BOOST_FUNCTION_STD_NS::type_info& check_type =
358
- * static_cast < const BOOST_FUNCTION_STD_NS::type_info*>( out_buffer.const_obj_ptr ) ;
374
+ } else if ( op == check_functor_type_tag) {
375
+ const BOOST_FUNCTION_STD_NS::type_info& check_type
376
+ = * out_buffer.type . type ;
359
377
if (BOOST_FUNCTION_COMPARE_TYPE_ID (check_type, typeid (Functor)))
360
378
out_buffer.obj_ptr = in_buffer.obj_ptr ;
361
379
else
362
380
out_buffer.obj_ptr = 0 ;
381
+ } else /* op == get_functor_type_tag */ {
382
+ out_buffer.type .type = &typeid (Functor);
383
+ out_buffer.type .const_qualified = false ;
384
+ out_buffer.type .volatile_qualified = false ;
363
385
}
364
386
}
365
387
@@ -374,6 +396,14 @@ namespace boost {
374
396
mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
375
397
}
376
398
399
+ // For member pointers, we use the small-object optimization buffer.
400
+ static inline void
401
+ manager (const function_buffer& in_buffer, function_buffer& out_buffer,
402
+ functor_manager_operation_type op, member_ptr_tag)
403
+ {
404
+ manager (in_buffer, out_buffer, op, mpl::true_ ());
405
+ }
406
+
377
407
public:
378
408
/* Dispatch to an appropriate manager based on whether we have a
379
409
function pointer or a function object pointer. */
@@ -384,7 +414,9 @@ namespace boost {
384
414
typedef typename get_function_tag<functor_type>::type tag_type;
385
415
switch (op) {
386
416
case get_functor_type_tag:
387
- out_buffer.const_obj_ptr = &typeid (functor_type);
417
+ out_buffer.type .type = &typeid (functor_type);
418
+ out_buffer.type .const_qualified = false ;
419
+ out_buffer.type .volatile_qualified = false ;
388
420
return ;
389
421
390
422
default :
@@ -439,6 +471,9 @@ namespace boost {
439
471
// Get back to the original pointer type
440
472
functor_wrapper_type* new_f = static_cast <functor_wrapper_type*>(copy);
441
473
out_buffer.obj_ptr = new_f;
474
+ } else if (op == move_functor_tag) {
475
+ out_buffer.obj_ptr = in_buffer.obj_ptr ;
476
+ in_buffer.obj_ptr = 0 ;
442
477
} else if (op == destroy_functor_tag) {
443
478
/* Cast from the void pointer to the functor_wrapper_type */
444
479
functor_wrapper_type* victim =
@@ -447,13 +482,17 @@ namespace boost {
447
482
wrapper_allocator.destroy (victim);
448
483
wrapper_allocator.deallocate (victim,1 );
449
484
out_buffer.obj_ptr = 0 ;
450
- } else /* op == check_functor_type_tag */ {
451
- const BOOST_FUNCTION_STD_NS::type_info& check_type =
452
- * static_cast < const BOOST_FUNCTION_STD_NS::type_info*>( out_buffer.const_obj_ptr ) ;
485
+ } else if ( op == check_functor_type_tag) {
486
+ const BOOST_FUNCTION_STD_NS::type_info& check_type
487
+ = * out_buffer.type . type ;
453
488
if (BOOST_FUNCTION_COMPARE_TYPE_ID (check_type, typeid (Functor)))
454
489
out_buffer.obj_ptr = in_buffer.obj_ptr ;
455
490
else
456
491
out_buffer.obj_ptr = 0 ;
492
+ } else /* op == get_functor_type_tag */ {
493
+ out_buffer.type .type = &typeid (Functor);
494
+ out_buffer.type .const_qualified = false ;
495
+ out_buffer.type .volatile_qualified = false ;
457
496
}
458
497
}
459
498
@@ -478,7 +517,9 @@ namespace boost {
478
517
typedef typename get_function_tag<functor_type>::type tag_type;
479
518
switch (op) {
480
519
case get_functor_type_tag:
481
- out_buffer.const_obj_ptr = &typeid (functor_type);
520
+ out_buffer.type .type = &typeid (functor_type);
521
+ out_buffer.type .const_qualified = false ;
522
+ out_buffer.type .volatile_qualified = false ;
482
523
return ;
483
524
484
525
default :
@@ -556,7 +597,6 @@ namespace boost {
556
597
*/
557
598
struct vtable_base
558
599
{
559
- vtable_base () : manager(0 ) { }
560
600
void (*manager)(const function_buffer& in_buffer,
561
601
function_buffer& out_buffer,
562
602
functor_manager_operation_type op);
@@ -586,7 +626,7 @@ class function_base
586
626
587
627
detail::function::function_buffer type;
588
628
vtable->manager (functor, type, detail::function::get_functor_type_tag);
589
- return *static_cast < const BOOST_FUNCTION_STD_NS::type_info*>( type.const_obj_ptr ) ;
629
+ return *type.type . type ;
590
630
}
591
631
592
632
template <typename Functor>
@@ -595,7 +635,9 @@ class function_base
595
635
if (!vtable) return 0 ;
596
636
597
637
detail::function::function_buffer type_result;
598
- type_result.const_obj_ptr = &typeid (Functor);
638
+ type_result.type .type = &typeid (Functor);
639
+ type_result.type .const_qualified = is_const<Functor>::value;
640
+ type_result.type .volatile_qualified = is_volatile<Functor>::value;
599
641
vtable->manager (functor, type_result,
600
642
detail::function::check_functor_type_tag);
601
643
return static_cast <Functor*>(type_result.obj_ptr );
@@ -611,7 +653,9 @@ class function_base
611
653
if (!vtable) return 0 ;
612
654
613
655
detail::function::function_buffer type_result;
614
- type_result.const_obj_ptr = &typeid (Functor);
656
+ type_result.type .type = &typeid (Functor);
657
+ type_result.type .const_qualified = true ;
658
+ type_result.type .volatile_qualified = is_volatile<Functor>::value;
615
659
vtable->manager (functor, type_result,
616
660
detail::function::check_functor_type_tag);
617
661
// GCC 2.95.3 gets the CV qualifiers wrong here, so we
0 commit comments