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