BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlf.h
Go to the documentation of this file.
1
/// @file bdlf.h
2
///
3
///
4
/// @defgroup bdlf Package bdlf
5
/// @brief Basic Development Library Functors (bdlf)
6
/// @addtogroup bdl
7
/// @{
8
/// @addtogroup bdlf
9
/// @{
10
/// * <a href="#bdlf-purpose"> Purpose</a>
11
/// * <a href="#bdlf-mnemonic"> Mnemonic </a>
12
/// * <a href="#bdlf-description"> Description </a>
13
/// * <a href="#bdlf-hierarchical-synopsis"> Hierarchical Synopsis </a>
14
/// * <a href="#bdlf-component-synopsis"> Component Synopsis </a>
15
/// * <a href="#bdlf-related-packages-in-package-group-bdl"> Related Packages in Package Group bdl </a>
16
/// * <a href="#bdlf-relationship-to-packages-in-bdl"> Relationship to Packages in bdl </a>
17
/// * <a href="#bdlf-functors-and-function-pointers"> Functors and Function Pointers </a>
18
/// * <a href="#bdlf-functors-in-the-bdlf-package"> Functors in the bdlf package </a>
19
/// * <a href="#bdlf-signature-specific-functors"> Signature-Specific Functors </a>
20
/// * <a href="#bdlf-envelope-letter-idiom"> Envelope-Letter Idiom </a>
21
/// * <a href="#bdlf-binders"> Binders </a>
22
/// * <a href="#bdlf-general-function-objects"> General (Run-Time Polymorphic) Function Objects </a>
23
/// * <a href="#bdlf-functors-and-binders"> Functors and Binders </a>
24
/// * <a href="#bdlf-usage"> Usage </a>
25
///
26
/// # Purpose {#bdlf-purpose}
27
/// Provide signature-specific function objects (functors).
28
///
29
/// # Mnemonic {#bdlf-mnemonic}
30
/// Basic Development Library Functors (bdlf)
31
///
32
/// @see
33
///
34
/// # Description {#bdlf-description}
35
/// The 'bdlf' package provides components to implement function
36
/// objects (functors) that return void and take between zero and nine arguments
37
/// of arbitrary type. Function objects created by 'bdlf' components can be
38
/// invoked in a manner similar to that of the following free function:
39
/// @code
40
/// void functionObject(arglist);
41
/// @endcode
42
/// where 'arglist' contains between zero and nine arguments. Functor classes are
43
/// differentiated by the number and type of arguments they expect. The 'bdlf'
44
/// package contains 10 separate components that differ in the number of arguments
45
/// their functors expect; within each component, templates are used to support
46
/// variations in argument type.
47
///
48
/// In addition, three components (@ref bdlf_bind , @ref bdlf_memfn and @ref bdlf_function )
49
/// provide more general functors that can conform to a specified prototype and
50
/// return an arbitrary type, and that can be invoked in the same manner as
51
/// before. The functors created by these two components currently support from
52
/// zero up to 14 arguments. @ref bdlf_bind provides compile-time polymorphism, and
53
/// adapts an invocable object so that it conforms to a different interface and
54
/// can be invoked with fewer arguments and/or with the arguments in a different
55
/// order. This transformation is type-safe, in that type violations provoke
56
/// compilation errors. @ref bdlf_memfn provides a wrapper that allows a member
57
/// function to be invoked like a free function, either by providing the object
58
/// instance as first parameter, or by wrapping the object instance inside the
59
/// function object. @ref bdlf_function provides run-time polymorphism and is
60
/// especially suited for callbacks because it adapts any invocable with a
61
/// compatible prototype to a specified callback interface, at run-time and
62
/// without the need for recompilation.
63
///
64
/// ## Hierarchical Synopsis {#bdlf-hierarchical-synopsis}
65
///
66
/// The 'bdlf' package currently has 6 components having 3 levels of physical
67
/// dependency. The list below shows the hierarchical ordering of the components.
68
/// The order of components within each level is not architecturally significant,
69
/// just alphabetical.
70
/// @code
71
/// 3. bdlf_bind
72
///
73
/// 2. bdlf_memfn
74
/// bdlf_noop
75
/// bdlf_overloaded
76
/// bdlf_placeholder
77
///
78
/// 1. bdlf_noop_cpp03 !PRIVATE!
79
/// @endcode
80
///
81
/// ## Component Synopsis {#bdlf-component-synopsis}
82
///
83
/// @ref bdlf_bind :
84
/// Provide a signature-specific function object (functor).
85
///
86
/// @ref bdlf_memfn :
87
/// Provide member function pointer wrapper classes and utility.
88
///
89
/// @ref bdlf_noop :
90
/// Provide a functor class that does nothing.
91
///
92
/// @ref bdlf_noop_cpp03 : !PRIVATE!
93
/// Provide C++03 implementation for bdlf_noop.h
94
///
95
/// @ref bdlf_overloaded :
96
/// Provide a type for constructing overload sets.
97
///
98
/// @ref bdlf_placeholder :
99
/// Provide a parameterized placeholder and specialized placeholders.
100
///
101
/// ## Related Packages in Package Group bdl {#bdlf-related-packages-in-package-group-bdl}
102
///
103
/// Package 'bdlf' is designed to use three other packages in 'bdl'. 'bdlf'
104
/// provides the primary interface that a client will see, and the other packages
105
/// play supporting roles.
106
///
107
/// The packages are:
108
///
109
/// 'bdlf':
110
/// Provides functors to clients in a canonical form.
111
///
112
/// 'bdlfr':
113
/// This package is *DEPRECATED*. A common reference-counted base class,
114
/// used by 'bdlfi'. These classes provide reference counting and object
115
/// deletion for derived classes.
116
///
117
/// 'bdlfi':
118
/// This package is *DEPRECATED*. Concrete reference-counted function
119
/// objects, held and managed by a 'bdlf' object; classes in 'bdlfi'
120
/// implement behavior declared in 'bdlfr'.
121
///
122
/// 'bdlfu':
123
/// This package is *DEPRECATED*. Factory method utilities to initialize
124
/// 'bdlf' functors by creating a reference-counted function object (from
125
/// 'bdlfi') and assigning it to a 'bdlf' functor. Subsequent invocations of
126
/// the 'bdlf' functor will be delegated to the 'bdlfi' object.
127
///
128
/// ## Relationship to Packages in bdl {#bdlf-relationship-to-packages-in-bdl}
129
///
130
/// The 'bdlf', 'bdlfr', 'bdlfi', and 'bdlfu' packages provide identical
131
/// functionality to the corresponding packages in the 'bce' package group:
132
/// 'bcef', 'bcefr', 'bcefi', and 'bcefu', respectively. The difference between
133
/// the two sets of packages is that the 'bce' packages provide thread safety,
134
/// whereas the 'bdl' packages do not. In particular, package 'bcefr' implements
135
/// reference counting via atomic operators provided in package @ref bces_atomicutil .
136
///
137
/// ## Functors and Function Pointers {#bdlf-functors-and-function-pointers}
138
///
139
/// Function pointers should be familiar to both C and C++ programmers. A
140
/// function pointer is a pointer to a C-style function. In C++, the function
141
/// pointer is declared to point to a function with a specific return type and a
142
/// specific number of arguments of specific types. For instance,
143
/// @code
144
/// void (*fp)(int, const char*);
145
/// @endcode
146
/// declares a function pointer 'fp' that points to a function returning 'void',
147
/// and taking exactly two arguments, an 'int' and a const pointer to 'char'.
148
///
149
/// Assume, then, that we have one or more functions declared with the matching
150
/// signature:
151
/// @code
152
/// void f1(int x, const char* s);
153
/// void f2(int x, const char* s);
154
/// @endcode
155
/// After assigning a value to the function pointer, we can call the corresponding
156
/// function:
157
/// @code
158
/// fp = f1;
159
/// .
160
/// .
161
/// .
162
/// int my_x = 0;
163
/// int my_s = "Text String";
164
/// fp(my_x, my_s); // invokes function f1
165
/// @endcode
166
/// Functors are objects that behave syntactically and semantically like
167
/// functions. Functors implement a function-call operator ('operator()') whose
168
/// signature characterizes the particular functor's type. In this example, for
169
/// instance, we could define a functor like this:
170
/// @code
171
/// class MyFunctor {
172
/// // Class MyFunctor can be used like a function.
173
/// .
174
/// .
175
/// .
176
/// public:
177
/// void operator()(int x, const char* s);
178
/// // this provides invocation semantics
179
/// .
180
/// .
181
/// .
182
/// };
183
///
184
/// MyFunctor fn;
185
/// .
186
/// .
187
/// .
188
/// int my_x = 0;
189
/// int my_s = "Text String";
190
/// fn(my_x, my_s); // "invokes" functor fn via fn::operator()
191
/// @endcode
192
/// Functors provide some interesting advantages over simple function pointers.
193
/// Unlike a function pointer, a functor may be created with one or more arbitrary
194
/// objects (sometimes called "user data") to be passed (typically as trailing
195
/// arguments) to the underlying function. By "pre-binding" particular arguments
196
/// to the underlying function, a functor can reduce the number of arguments a
197
/// caller must supply when the functor is invoked. In this way, function objects
198
/// can be used to coerce functions with extra arguments of arbitrary type into a
199
/// standard calling signature. Even (non-'static') *member* functions can be
200
/// encapsulated within functors and treated uniformly, simply by supplying the
201
/// appropriate object at construction. Both the *object* pointer and a *member*
202
/// *function* pointer are stored in the functor; the given object pointer is
203
/// dereferenced when the functor is invoked.
204
///
205
/// ## Functors in the bdlf package {#bdlf-functors-in-the-bdlf-package}
206
///
207
///
208
/// ### Signature-Specific Functors {#bdlf-signature-specific-functors}
209
///
210
/// Individual components are "numbered" to indicate the number of arguments
211
/// (between 0 and 6) that a particular functor accepts. Each component defines a
212
/// templated class, whose template parameters correspond in number to the functor
213
/// arguments. When instantiated, the template argument types match the argument
214
/// types used in invoking the functor. The component name is @ref bdlf_vfunc
215
/// followed by 0 to 6; the letter 'v' indicates that the corresponding functor
216
/// will return 'void'. For the example above, we would use component
217
/// @ref bdlf_vfunc2 to create a functor object whose 'operator()' member function
218
/// obeys the required signature.
219
/// @code
220
/// #include <bdlf_vfunc2.h>
221
///
222
/// bdlf_Vfunc2<int, const char*> fn; // template arguments specify arg
223
/// // types
224
/// // NOTE: This example is incomplete.
225
/// // We still need code to initialize 'fn'
226
/// .
227
/// .
228
/// .
229
/// int my_x = 0;
230
/// int my_s = "Text String";
231
/// fn(my_x, my_s); // "invokes" functor fn
232
/// @endcode
233
/// Before a 'bdlf' functor is invoked as illustrated, the client is responsible
234
/// for ensuring that it is valid; that is, it must contain a pointer to a
235
/// function that will be called when the functor is invoked. The function to be
236
/// called is external to the functor, and supplied by the client. This "external
237
/// function" may be a free function, a static class method, or a (non-'static')
238
/// member function for some class. The client, then, needs a canonical
239
/// mechanism, regardless of the function type, to create a reference to that
240
/// function, and to bind the reference to the 'bdlf' functor.
241
///
242
/// The most common way to accomplish this is to use a "factory method" defined in
243
/// the 'bdlfu' package. The 'bdlfu' package contains 10 components which provide
244
/// these factory methods. Parallel to 'bdlf', these components are "numbered" to
245
/// support functors with different numbers of arguments. The factory methods are
246
/// also templatized to support varying argument types.
247
///
248
/// Each 'bdlfu' component contains 4 different types of factory methods, varying
249
/// by the type of function pointer required. For example, @ref bdlfu_vfunc2 defines
250
/// the following *factory* *method* *families*:
251
/// @code
252
/// bdlfu_Vfunc2::makeF(); // generate a pointer to a free function
253
/// // and assign it to a 'bdlf_Vfunc2' object
254
/// bdlfu_Vfunc2::makeM(); // generate a pointer to a member function
255
/// // and assign it to a 'bdlf_Vfunc2' object
256
/// bdlfu_Vfunc2::makeC() // generate a pointer to a const member
257
/// // function and assign it to a 'bdlf_Vfunc2'
258
/// // object
259
/// bdlfu_Vfunc2::makeNull(); // initialize a 'bdlf_Vfunc2' object with
260
/// // an empty function
261
/// @endcode
262
/// These factory methods (except for 'makeNull') are templatized to support
263
/// different return and argument types; in addition, each *factory* *method*
264
/// *family* consists of a set of overloaded functions that support varying
265
/// numbers of arguments on the underlying functions (member or free). All
266
/// classes returned by functions in component @ref bdlfu_vfunc2 are defined in
267
/// component @ref bdlfi_vfunc2 . See package documentation for the {'bdlfu'} package
268
/// for details.
269
///
270
/// For the simple example above, we would use component 'bdlfu_Vfunc2' as follows
271
/// to initialize the 'bdlf_Vfunc2' object:
272
/// @code
273
/// #include <bdlf_vfunc2.h>
274
/// #include <bdlfu_vfunc2.h>
275
///
276
/// void f1(int x, const char* s);
277
/// void f2(int x, const char* s);
278
///
279
/// bdlf_Vfunc2<int, const char*> fn; // template arguments define arg types
280
/// bdlfu_Vfunc2::makeF(&fn,f1); // bind functor fn to function f1
281
/// .
282
/// .
283
/// .
284
/// int my_x = 0;
285
/// int my_s = "Text String";
286
/// fn(my_x, my_s); // "invokes" functor fn
287
/// @endcode
288
/// The 'bdlfu_Vfunc2::makeF' *factory* *method* in the above example expects two
289
/// arguments. The first is a pointer to the functor object itself, and the
290
/// second is a pointer to a free function with a signature matching the functor
291
/// object, that is, expecting args of 'int' and 'const char*', and returning
292
/// 'void'.
293
///
294
/// The 'makeF()' functions create instances of classes from the 'bdlfi'
295
/// component; the specific classes are determined by the number and types of
296
/// arguments on the 'bdlf' functor and the free function. Similarly, class
297
/// member functions can be used to initialize a 'bdlf' functor by invoking a
298
/// 'bdlfu_Vfunc2::makeM()' or 'bdlfu_Vfunc2::makeC()' function.
299
///
300
/// The 'bdlfu' and 'bdlfi' packages will also allow clients to match a functor to
301
/// a free or member function in situations where the function requires more
302
/// arguments than the functor invocation can support. See the documentation for
303
/// package {'bdlfu'} for details describing how to do this; see package
304
/// documentation for {'bdlfi'} for implementation details.
305
///
306
/// Note that because each required argument type 'T' is passed by ('const' 'T&'),
307
/// a compiler will generate an error if the user declares a callback function
308
/// taking an argument via a non-'const' reference parameter. This is intended to
309
/// support and enforce the rule that all modifiable arguments are passed using
310
/// pointers and not using references. For rare situations where clients want to
311
/// use a callback function supplied by a third party, and that callback function
312
/// uses non-'const' references, a wrapper function must be declared that converts
313
/// non-'const' references to 'const' references or pointers as appropriate.
314
///
315
/// ### Envelope-Letter Idiom {#bdlf-envelope-letter-idiom}
316
///
317
/// The functors in the 'bdlf' package are implemented using the envelope-letter
318
/// idiom. The classes in 'bdlf' are *"envelopes"*; classes in 'bdlfr' and
319
/// 'bdlfi' are *"letters"*. The use of the envelope-letter idiom allows clients
320
/// to wrap arbitrary functions, whose signatures may differ from the function
321
/// signatures in 'bdlf', with functors that support standard, well-known
322
/// signatures.
323
///
324
/// Each 'bdlf_Vfunc*' functor *(envelope)* holds a pointer to an
325
/// object *(letter)* from the corresponding 'bdlfi_vfunc*' component. The 'bdlf'
326
/// *envelope* forwards or delegates client requests to its *letter* object: in
327
/// particular, the 'operator()' member function used by clients to invoke the
328
/// functor is delegated to the *letter* object for execution.
329
///
330
/// The *letter* object is polymorphic: all *letter* classes in a given 'bdlfi'
331
/// component are derived from a common protocol or abstract base class (defined
332
/// in 'bdlfr'). The 'bdlf' *envelope* uses the abstract 'bdlfr' protocol to
333
/// delegate invocation requests. Different polymorphic *letter* types are used
334
/// to support different external function types and signatures, and the single
335
/// *envelope* type is used to provide a consistent function signature to clients.
336
///
337
/// Since polymorphism is used to support different bindings to external member or
338
/// free functions, clients must be able to generate a specific type of *letter*
339
/// object for a given *envelope*, based upon the type and signature of the
340
/// specific external function. This may be done directly through public
341
/// interfaces of the corresponding 'bdlfi' component, but in most cases it is
342
/// simpler to use a suite of template functions provided by the corresponding
343
/// 'bdlfu' package. Different template functions are provided to match (1) the
344
/// desired function-call-operator signature and (2) the supplied user data.
345
/// Because the C++ compiler will deduce template parameters from argument types,
346
/// clients need not specify them. See the {'bdlfu'} package for more information
347
/// on populating 'bdlf' functors with specific *letter* objects.
348
///
349
/// See also J.O. Coplien, "Advanced Programming Styles and Idioms", Sections
350
/// 5.5-5.6, for a complete discussion of the envelope/letter idiom.
351
///
352
/// ### Binders {#bdlf-binders}
353
///
354
/// The @ref bdlf_bind component provides a mechanism for creating function objects
355
/// different from the 'bdlf_vfunc*' components. @ref bdlf_bind is used to *adapt*
356
/// an invocable object so that it conforms to a different interface and can be
357
/// invoked with fewer arguments and/or with the arguments in a different order.
358
/// It does this by *binding* some or all of the original invocable's arguments to
359
/// fixed values that are known at construction time and binding the remaining
360
/// arguments to placeholders for arguments that are provided at invocation time.
361
/// A binder can be used as an argument for any template function that requires an
362
/// invocable with compatible parameters.
363
///
364
/// The @ref bdlf_bind component defines binder objects and factory methods that can
365
/// bind any arguments into a functor in any order, enabling some of the arguments
366
/// of the invocable to be specified at the construction time, and leaving (via
367
/// place-holders, defined in component @ref bdlf_placeholder ) some others to be
368
/// specified (later) at invocation time. A binder is created by one of the three
369
/// *factory* *method* *families* defined in component @ref bdlf_bind :
370
/// @code
371
/// bdlf_BindUtil::bind(); // generate a binder with specified invocable and
372
/// // bound arguments (invocation arguments are
373
/// // indicated by place-holders)
374
/// bdlf_BindUtil::bindA(); // same as above but also specify the allocator
375
/// // used to supply memory for creating the binder
376
/// bdlf_BindUtil::bindR(); // same as 'bdlf_BindUtil::bind()' but explicitly
377
/// // specify the return type (in case it cannot be
378
/// // deduced by the compiler but should not be left
379
/// // undefined)
380
/// @endcode
381
/// Binders where the signature of the invocable can be deduced are called
382
/// *explicit*. Not all binders are explicit. For non-explicit binders, the
383
/// signature of a 'bdlf_Bind' object is not embedded in the type, and several
384
/// overloads can be invoked through the same binder. Unlike 'bdlf_Vfunc*'
385
/// objects, different binders accepting the same signature may have different
386
/// types depending on the types of the bound arguments if they are non-explicit.
387
/// The return type (not necessarily void) is also part of the signature. Thus,
388
/// @ref bdlf_bind provides compile-time polymorphism but not run-time polymorphism.
389
///
390
/// A broad discussion of binding, along with limitations of the 'usage examples,
391
/// can be found in the component documentation of component @ref bdlf_bind .
392
///
393
/// ### General (Run-Time Polymorphic) Function Objects {#bdlf-general-function-objects}
394
///
395
/// In addition to signature-specific objects and binders, the 'bdlf' package
396
/// provides a run-time polymorphic 'bdlf_Function' template. A 'bdlf_Function'
397
/// instantiation is capable of holding *any* invocable object of compatible
398
/// prototype, including a function pointer, 'bdlf_MemFn' wrapper, any concrete
399
/// implementation of the 'bdlfr_Vfunc*'protocols, any instances of the
400
/// 'bdlf_Vfunc' family, and any other function object having an 'operator()'
401
/// method including an instance of a 'bdlf_Bind' instantiation.
402
///
403
/// Like a binder, a 'bdlf_Function' instantiation can have a return value (or
404
/// return 'void'). An instance does not store bound arguments directly. It
405
/// accepts all its arguments at invocation time only, although using polymorphic
406
/// representations and the 'bdlfu_Vfunc*::make*' factory methods, it is possible
407
/// to bind the last arguments of an invocable and wrap this into a
408
/// 'bdlf_Function' object which will then accept only the remaining arguments
409
/// upon invocation. As mentioned above, it is also possible to assign a
410
/// 'bdlf_Bind' object to a 'bdlf_Function' instance to bind and route arguments
411
/// to the invocable in an arbitrary manner.
412
///
413
/// Unlike a binder, the signature of a 'bdlf_Function' object is part of the type
414
/// and invocation arguments are cast to their corresponding type before they are
415
/// passed to the invocable. Most importantly, the same functor may be assigned
416
/// from various types (pointer to function, 'bdlf_MemFn' wrapper, user-defined
417
/// function objects, or even 'bdlf_Bind' binders).
418
///
419
/// ### Functors and Binders {#bdlf-functors-and-binders}
420
///
421
/// 'bdlf_Function' objects (functors) and 'bdlf_Bind' objects (binders) are both
422
/// mechanisms for binding arguments and calling an invocable. They differ in
423
/// their purpose, though. In the last section, we detailed the main features of
424
/// the @ref bdlf_function and @ref bdlf_bind components. In this section we point out
425
/// the differences, and how they interact.
426
///
427
/// The main difference is compile-time (for @ref bdlf_bind ) vs. run-time (for
428
/// @ref bdlf_function ) polymorphism. An instantiation of 'bdlf_Function' is a type
429
/// of functor that can hold any invocable object with compatible prototype.
430
/// Regardless of what type of (compatible) invocable is used to create the
431
/// 'bdlf_Function', the type of the resulting functor does not change. Thus,
432
/// 'bdlf_Function' has run-time polymorphism and is ideally suited for callbacks
433
/// because it *adapts* the invocable to the callback interface. Run-time
434
/// polymorphism is extremely useful for defining callback types and storing
435
/// callbacks, since passing a new type of callback does not require
436
/// re-compilation. Compile-time polymorphism provides the ability to invoke
437
/// several overloads through the same functor (binder) and to bind and route
438
/// arguments to the invocable in an arbitrary manner.
439
///
440
/// In cases where both binders and functors could be used, 'bdlf_Function' has
441
/// certain advantages, not least of which is simplicity (leading to shorter
442
/// compilation times), and the memory optimization documented below, whereby
443
/// small objects are constructed in-place but larger objects are dynamically
444
/// allocated. Note that binders are always constructed in-place and can have
445
/// rather large footprints. Functors (including instances of 'bdlfr_Vfunc*'
446
/// derived types) can implement various strategies like sharing and copy-on-write
447
/// to reduce the cost of copying and the footprint at the same time.
448
///
449
/// ## Usage {#bdlf-usage}
450
///
451
/// 'bdlf'-style functors provide a type-neutral, exception-safe (and
452
/// *potentially*, but not yet, thread-safe) *properly* *managed* alternative to
453
/// the traditional callback paradigm (where "client data" is placed in a single
454
/// structure whose address is cast to type 'void *'). The following example
455
/// illustrates how functor callbacks can be added to a graphical object.
456
///
457
/// Let's suppose that the implementor of the 'MyGuiButton' class allows the
458
/// client to specify a callback function that should be called whenever a button
459
/// is pressed. Furthermore, the implementor agrees to provide to the callback
460
/// function two arguments at its invocation: a modifiable object of type
461
/// 'MyGuiContext', and a non-modifiable object of type 'MyGuiLocation'.
462
/// @code
463
/// class MyGuiContext {
464
/// int d_changedFlag;
465
///
466
/// public:
467
/// MyGuiContext() : d_changedFlag(0) { }
468
/// int isChanged() { return d_changedFlag; }
469
/// void changeState() { ++d_changedFlag; }
470
///
471
/// // 'MyGuiContext' implementation
472
/// };
473
///
474
/// class MyGuiLocation {
475
/// public:
476
/// MyGuiLocation() { };
477
///
478
/// // 'MyGuiLocation' implementation
479
/// };
480
/// @endcode
481
/// Here is the implementation of the 'MyGuiButton' class:
482
/// @code
483
/// class MyGuiButton {
484
/// bdlf_Vfunc2<MyGuiContext *, MyGuiLocation> d_callback;
485
/// // Functor to execute when button is pressed.
486
///
487
/// public:
488
/// MyGuiButton(const bdlf_Vfunc2<MyGuiContext *,
489
/// MyGuiLocation>& buttonPressCallback);
490
/// // Create a graphical button object that executes the
491
/// // specified callback when 'pressButton' is invoked.
492
///
493
/// void pressButton(MyGuiContext *context,
494
/// const MyGuiLocation& location);
495
/// // Execute the callback owned by this button object.
496
/// };
497
///
498
/// MyGuiButton::MyGuiButton(const bdlf_Vfunc2<MyGuiContext *,
499
/// MyGuiLocation>& buttonPressCallback)
500
/// : d_callback(buttonPressCallback) // Retain a "copy" of the specified
501
/// // functor.
502
/// {
503
/// }
504
///
505
/// void MyGuiButton::pressButton(MyGuiContext *context,
506
/// const MyGuiLocation& location)
507
/// {
508
/// d_callback(context, location);
509
/// // Execute the contained callback object.
510
/// }
511
/// @endcode
512
/// The 'context' and 'location' arguments are mandatory for every function called
513
/// at the press of the button (the number '2' in the name of 'bdlf_Vfunc2' class
514
/// specifies the number of required arguments). However, we also allow the user
515
/// of 'MyGuiButton' class to invoke the function with a number of additional
516
/// parameters, as in the 'buttonpressFunction' function presented below.
517
/// @code
518
/// static void buttonpressFunction(MyGuiContext *a,
519
/// const MyGuiLocation& b,
520
/// int *invocationCounter)
521
/// // This function will be invoked by a functor to increment the
522
/// // specified 'invocationCounter'.
523
/// {
524
/// a->changeState();
525
/// ++*invocationCounter;
526
/// }
527
/// @endcode
528
/// The 'bdlf_Vfunc2<MyGuiContext, MyGuiLocation>' class used in 'MyGuiButton'
529
/// class has a private member of an abstract class @ref bdlfr_vfunc2 , whose
530
/// 'execute' method is called when the functor is being called. The 'execute'
531
/// method of the @ref bdlfr_vfunc2 class, the functor invocation operator of the
532
/// 'bdlf_Vfunc2' class, and the 'pressButton' method of 'MyGuiButton' class have
533
/// two parameters. The 'buttonpressFunction' callback function, however, has to
534
/// be called with three arguments. To achieve the proper calling signature the
535
/// user implements a concrete class derived from @ref bdlfr_vfunc2 as follows:
536
/// @code
537
/// template <class F, class A1, class A2, class D1>
538
/// class FuncRep : public bdlfr_Vfunc2<A1, A2> {
539
/// // This class defines the representation for a function object (functor),
540
/// // characterized by a function-call operator taking two arguments and
541
/// // returning 'void', that holds a pure procedure (i.e., free function,
542
/// // static member function, or functor) taking one additional trailing
543
/// // argument, and this argument's corresponding value.
544
///
545
/// F d_f; // function pointer or function object (functor)
546
/// D1 d_d1; // first embedded argument
547
///
548
/// private:
549
/// // not implemented
550
/// FuncRep(const FuncRep<F, A1, A2, D1>&);
551
/// FuncRep<F, A1, A2, D1>& operator=(const FuncRep<F, A1, A2, D1>&);
552
///
553
/// private:
554
/// ~FuncRep()
555
/// // Destroy this functor. Note that destructor can be invoked only
556
/// // through the static 'deleteObject' method of the base class.
557
/// {
558
/// };
559
///
560
/// public:
561
/// // CREATORS
562
/// FuncRep(const F& procedure,
563
/// const D1& embeddedArg1,
564
/// bdlma_Allocator *basicAllocator)
565
/// // Create a representation for a function object (functor) taking two
566
/// // arguments and returning 'void', using the specified 'procedure'
567
/// // taking 1 additional trailing argument, and this argument's
568
/// // specified 'embeddedArg1' value. Use the specified
569
/// // 'basicAllocator' to supply memory.
570
/// : bdlfr_Vfunc1<A1, A2>(basicAllocator)
571
/// , d_f(procedure)
572
/// , d_d1(embeddedArg1)
573
/// {
574
/// };
575
///
576
/// // ACCESSORS
577
/// void execute(const A1& argument1, const A2& argument2) const
578
/// // Invoke the underlying procedure (free function, static member
579
/// // function, or functor) with the specified 'argument1' and
580
/// // 'argument2' followed by the argument value specified at
581
/// // construction.
582
/// {
583
/// d_f(argument1, argument2, d_d1);
584
/// };
585
/// };
586
/// @endcode
587
/// Note that the required arguments are passed in at the functor invocation, and
588
/// optional arguments are passed in at the functor initialization. By BDE
589
/// convention, a function signature consists of output parameters, and then input
590
/// parameters. Since here we have two parameter lists (one passed in by the
591
/// caller, and one passed in by the callee) we can follow this convention within
592
/// each list only. We choose to pass in first the required arguments (passed by
593
/// the caller) and then the optional arguments (supplied by the callee). This
594
/// order allows a callee to add parameters easily at the end of the function
595
/// parameter list. The number of required parameters is a part of the
596
/// 'MyGuiButton' interface, and hence will never change.
597
///
598
/// The following code shows how we:
599
///
600
/// 1. Create the functor representation-(letter).
601
///
602
/// 2. Create the functor initialized with the representation.
603
///
604
/// 3. Register the functor as a callback with an instance of the 'MyGuiButton'
605
/// class.
606
///
607
/// 4. Invoke the functor.
608
///
609
/// The code is as follows:
610
/// @code
611
/// // (1) Create the representation.
612
///
613
/// typedef void (*BpFun)(const MyGuiContext *, const MyGuiLocation&, int *);
614
/// bdlma_Allocator *myAllocator = bdlma_Default::defaultAllocator();
615
///
616
/// int globalCounter = 0;
617
///
618
/// bdlfr_Vfunc2<MyGuiContext *, MyGuiLocation> *rep = new(myAllocator)
619
/// FuncRep<BpFun, MyGuiContext *, MyGuiLocation, int*>
620
/// (buttonpressFunction, &globalCounter, myAllocator);
621
///
622
/// // (2) Create the functor using the representation.
623
///
624
/// bdlf_Vfunc2<MyGuiContext *, MyGuiLocation> callbackFunctor(rep);
625
///
626
/// // (3) Register the functor as a callback.
627
///
628
/// MyGuiButton button(callbackFunctor);
629
///
630
/// // (4) Use the object.
631
///
632
/// MyGuiContext gc;
633
/// const MyGuiLocation gl; assert(0 == globalCounter);
634
/// assert(0 == gc.isChanged());
635
/// button.pressButton(&gc, gl); assert(1 == globalCounter);
636
/// assert(1 == gc.isChanged());
637
/// button.pressButton(&gc, gl); assert(2 == globalCounter);
638
/// assert(2 == gc.isChanged());
639
/// @endcode
640
///
641
/// @}
642
/** @} */
doxygen_input
bde
groups
bdl
bdlf
doc
bdlf.h
Generated by
1.9.8