BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_function.h
Go to the documentation of this file.
1/// @file bslstl_function.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_function.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_FUNCTION
9#define INCLUDED_BSLSTL_FUNCTION
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_function bslstl_function
15/// @brief Provide a polymorphic function object with a specific prototype.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_function
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_function-purpose"> Purpose</a>
25/// * <a href="#bslstl_function-classes"> Classes </a>
26/// * <a href="#bslstl_function-description"> Description </a>
27/// * <a href="#bslstl_function-invocation"> Invocation </a>
28/// * <a href="#bslstl_function-allocator-usage"> Allocator Usage </a>
29/// * <a href="#bslstl_function-small-object-optimization"> Small-object Optimization </a>
30/// * <a href="#bslstl_function-usage"> Usage </a>
31/// * <a href="#bslstl_function-example-1-polymorphic-invocation"> Example 1: Polymorphic Invocation </a>
32/// * <a href="#bslstl_function-example-2-use-in-a-generic-algorithm"> Example 2: Use in a Generic Algorithm </a>
33/// * <a href="#bslstl_function-example-3-a-parallel-work-queue"> Example 3: A Parallel Work queue </a>
34///
35/// # Purpose {#bslstl_function-purpose}
36/// Provide a polymorphic function object with a specific prototype.
37///
38/// # Classes {#bslstl_function-classes}
39///
40/// - bsl::function: polymorphic function object with a specific prototype.
41///
42/// **Canonical header:** bsl_functional.h
43///
44/// # Description {#bslstl_function-description}
45/// This component provides a single class template,
46/// `bsl::function`, implementing the standard template `std::function`, a
47/// runtime-polymorphic wrapper that encapsulates an arbitrary callable object
48/// (the *target*) and allows the wrapped object to be invoked. `bsl::function`
49/// extends `std::function` by adding allocator support in a manner consistent
50/// with standards proposal P0987 (http://wg21.link/P0987).
51///
52/// Objects of type `bsl::function` generalize the notion of function pointers
53/// and are generally used to pass callbacks to a non-template function or
54/// class. For example, `bsl::function<RET (ARG1, ARG2, ...)>` can be used
55/// similarly to `RET (*)(ARG1, ARG2, ...)` but, unlike the function pointer,
56/// the `bsl::function` can hold a non-function callable type such as pointer to
57/// member function, pointer to member data, lambda expression, or functor
58/// (class type having an `operator()`). A `bsl::function` can also be "empty",
59/// i.e., having no target object. In a `bool` context, a `bsl::function`
60/// object will evaluate to false if it is empty, and true otherwise. The
61/// target type is determined at runtime using *type* *erasure* in the
62/// constructors and can be changed by means of assignment, but the function
63/// prototype (argument types and return type) is specified as a template
64/// parameter at compile time.
65///
66/// An instantiation of `bsl::function` is an in-core value-semantic type whose
67/// salient attributes are the type and value of its target, if any. The
68/// `bsl::function` owns the target object and manages its lifetime; copying or
69/// moving the `bsl::function` object copies or moves the target and destroying
70/// the `bsl::function` destroys the target. Somewhat counter-intuitively, the
71/// target is always mutable within the `bsl::function`; when wrapping a class
72/// type, calling a `bsl::function` can modify its target object, even if the
73/// `bsl::function` itself is const-qualified.
74///
75/// Although, as a value-semantic type, `bsl::function` does have an abstract
76/// notion of "value", there is no general equality operator comparing between
77/// two `bsl::function` objects. This limitation is a consequence of the target
78/// type not being required to provide equality comparison operators. The
79/// `operator==` overloads that *are* provided compare a `bsl::function` against
80/// the null pointer and do not satisfy the requirements we typically expect for
81/// value-semantic equality operators.
82///
83/// ## Invocation {#bslstl_function-invocation}
84///
85///
86/// Calling an empty `bsl::function` object will cause it to throw a
87/// `bsl::bad_function_call` exception. Given a non-empty object of type
88/// `bsl::function<RET(ARG0, ARG1, ...)>` invoked with arguments `arg0`, `arg1`,
89/// ..., invocation of the target follows the definition of *INVOKE* in section
90/// [func.require] of the C++ standard. These rules are summarized in the
91/// following table:
92/// @code
93/// +----------------------------+-----------------------+
94/// | Type of target object, 'f' | Invocation expression |
95/// +============================+=======================+
96/// | Functor, function, or | f(arg0, arg1, ...) |
97/// | pointer to function | |
98/// +----------------------------+-----------------------+
99/// | Pointer to member function | (arg0X.*f)(arg1, ...) |
100/// +----------------------------+-----------------------+
101/// | Pointer to member data | arg0X.*f |
102/// +----------------------------+-----------------------+
103/// @endcode
104/// The arguments to `f` must be implicitly convertible from the corresponding
105/// argument types `ARG0`, `ARG1`, ... and the return value of the call
106/// expression must be implicitly convertible to `RET`, unless `RET` is `void`.
107///
108/// In the case of a pointer to member function, `R (T::*f)(...)`, or pointer to
109/// data member `R T::*f`, `arg0X` is one of the following:
110///
111/// * `arg0` if `ARG0` is `T` or derived from `T`
112/// * `arg0.get()` if `ARG0` is a specialization of @ref reference_wrapper
113/// * `(*arg0)` if `ARG0` is a pointer type or pointer-like type (e.g., a smart
114/// pointer).
115///
116/// Note that, consistent with the C++ Standard definition of *INVOKE*, we
117/// consider pointer-to-member-function and pointer-to-member-data types to be
118/// "callable" even though, strictly speaking, they cannot be called directly
119/// due to the lack of an `operator()`.
120///
121/// ## Allocator Usage {#bslstl_function-allocator-usage}
122///
123///
124/// The C++11 standard specified a type erasure scheme for allocator support in
125/// `std::function`. This specification was never implemented by any vendor or
126/// popular open-source standard library and allocator support was removed from
127/// the 2017 standard version of `std::function`. A new design for
128/// allocator support using `std::pmr::polymorphic_allocator` instead of type
129/// erasure is currently part of version 3 of the Library Fundamentals Technical
130/// Specification (LFTS 3), after acceptance of paper P0987
131/// (http://wg21.link/P0987). This component follows the P0987 specification,
132/// substituting `bsl::allocator` for `std::pmr::polymorphic_allocator`.
133///
134/// `bsl::function` meets the requirements for an allocator-aware type.
135/// Specifically:
136///
137/// * The type `allocator_type` is an alias for `bsl::allocator<char>`,
138/// * Every constructor can be invoked with an allocator argument, using the
139/// `bsl::allocator_arg_t` leading-allocator argument convention.
140/// * `get_allocator()` returns the allocator specified at construction.
141///
142/// There are two uses for the allocator in `bsl::function`:
143///
144/// 1. To allocate storage for holding the target object.
145/// 2. To pass to the constructor of the wrapped object if the wrapped object is
146/// allocator aware.
147///
148/// ## Small-object Optimization {#bslstl_function-small-object-optimization}
149///
150///
151/// A `bsl::function` class has a buffer capable of holding a small callable
152/// object without allocating dynamic memory. The buffer is guaranteed to be
153/// large enough to hold a pointer to function, pointer to member function,
154/// pointer to member data, a `bsl::reference_wrapper`, or a stateless functor.
155/// In practice, it is large enough to hold many stateful functors up to six
156/// times the size of a `void *`. Note that, even if the target object is
157/// stored in the small object buffer, memory might still be allocated by the
158/// target object itself.
159///
160/// There are only two circumstances under which `bsl::function` will store the
161/// target object in allocated memory:
162///
163/// 1. If the object is too large to fit into the small object buffer
164/// 2. If the object has a move constructor that might throw an exception
165///
166/// The second restriction allows the move constructor and swap operation on
167/// `bsl::function` to be `noexcept`, as required by the C++ Standard.
168///
169/// ## Usage {#bslstl_function-usage}
170///
171///
172/// In this section we show intended use of this component.
173///
174/// ### Example 1: Polymorphic Invocation {#bslstl_function-example-1-polymorphic-invocation}
175///
176///
177/// In this example, we create a single `bsl::function` object, then assign it
178/// to callable objects of different types at run time.
179///
180/// First, we define a simple function that returns the XOR of its two integer
181/// arguments:
182/// @code
183/// int intXor(int a, int b) { return a ^ b; }
184/// @endcode
185/// Next, we create a `bsl::function` that takes two integers and returns an
186/// integer. Because we have not initialized the object with a target, it
187/// starts out as empty and evaluates to false in a Boolean context:
188/// @code
189/// void main()
190/// {
191/// bsl::function<int(int, int)> funcObject;
192/// assert(! funcObject);
193/// @endcode
194/// Next, we use assignment to give it the value of (a pointer to) `intXor` and
195/// test that we can invoke it to get the expected result:
196/// @code
197/// funcObject = intXor;
198/// assert(funcObject);
199/// assert(5 == funcObject(6, 3));
200/// @endcode
201/// Next, we assign an instance of `std::plus<int>` functor to `funcObject`,
202/// which then holds a copy of it, and again test that we get the expected
203/// result when we invoke `funcObject`.
204/// @code
205/// funcObject = std::plus<int>();
206/// assert(funcObject);
207/// assert(9 == funcObject(6, 3));
208/// @endcode
209/// Then, if we are using C++11 or later, we assign it to a lambda expression
210/// that multiplies its arguments:
211/// @code
212/// #if BSLS_COMPILERFEATURES_CPLUSPLUS >= 201103L
213/// funcObject = [](int a, int b) { return a * b; };
214/// assert(funcObject);
215/// assert(18 == funcObject(6, 3));
216/// #endif
217/// @endcode
218/// Finally, we assign `funcObject` to `nullptr`, which makes it empty again:
219/// @code
220/// funcObject = bsl::nullptr_t();
221/// assert(! funcObject);
222/// }
223/// @endcode
224///
225/// ### Example 2: Use in a Generic Algorithm {#bslstl_function-example-2-use-in-a-generic-algorithm}
226///
227///
228/// Suppose we want to define an algorithm that performs a mutating operation on
229/// every element of an array of integers. The inputs are pointers to the first
230/// and last element to transform, a pointer to the first element into which the
231/// to write the output, and an operation that takes an integer in and produces
232/// an integer return value. Although the pointer arguments have known type
233/// (`int *`), the type of the transformation operation can be anything that can
234/// be called with an integral argument and produces an integral return value.
235/// We do not want to accept this operation as a template argument, however
236/// (perhaps because our algorithm is sufficiently complex and/or proprietary
237/// that we want to keep it out of header files). We solve these disparate
238/// requirements by passing the operation as a `bsl::function` object, whose
239/// type is known at compile time but which can be set to an arbitrary
240/// operation at run time:
241/// @code
242/// /// Apply my special algorithm to the elements in the contiguous address
243/// /// range from the specified `begin` pointer up to but not including the
244/// /// specified `end` pointer, writing the result to the contiguous range
245/// /// starting at the specified `output` pointer. The specified `op`
246/// /// function is applied to each element before it is fed into the
247/// /// algorithm.
248/// void myAlgorithm(const int *begin,
249/// const int *end,
250/// int *output,
251/// const bsl::function<int(int)>& op);
252/// @endcode
253/// For the purpose of illustration, `myAlgorithm` is a simple loop that
254/// invokes the specified `op` on each element in the input range and writes it
255/// directly to the output:
256/// @code
257/// void myAlgorithm(const int *begin,
258/// const int *end,
259/// int *output,
260/// const bsl::function<int(int)>& op)
261/// {
262/// for (; begin != end; ++begin) {
263/// *output++ = op(*begin);
264/// }
265/// }
266/// @endcode
267/// Next, we define input and output arrays to be used throughout the rest of
268/// this example:
269/// @code
270/// static const std::size_t DATA_SIZE = 5;
271/// static const int testInput[DATA_SIZE] = { 4, 3, -2, 9, -7 };
272/// static int testOutput[DATA_SIZE];
273/// @endcode
274/// Next, we define a function that simply negates its argument:
275/// @code
276/// long negate(long v) { return -v; }
277/// // Return the arithmetic negation of the specified 'v' integer.
278/// @endcode
279/// Then, we test our algorithm using our negation function:
280/// @code
281/// /// Test the use of the `negation` function with `myAlgorithm`.
282/// bool testNegation()
283/// {
284/// myAlgorithm(testInput, testInput + DATA_SIZE, testOutput, negate);
285///
286/// for (std::size_t i = 0; i < DATA_SIZE; ++i) {
287/// if (-testInput[i] != testOutput[i]) {
288/// return false; // RETURN
289/// }
290/// }
291/// return true;
292/// }
293/// @endcode
294/// Note that the prototype for `negate` is not identical to the prototype used
295/// to instantiate the `op` argument in `myAlgorithm`. All that is required is
296/// that each argument to `op` be convertible to the corresponding argument in
297/// the function and that the return type of the function be convertible to the
298/// return type of `op`.
299///
300/// Next, we get a bit more sophisticated and define an operation that produces
301/// a running sum over its inputs. A running sum requires holding on to state,
302/// so we define a functor class for this purpose:
303/// @code
304/// /// Keep a running total of all of the inputs provided to `operator()`.
305/// class RunningSum {
306///
307/// // DATA
308/// int d_sum;
309///
310/// public:
311/// // CREATORS
312///
313/// // Create a `RunningSum` with initial value set to the specified
314/// // `initial` argument.
315/// explicit RunningSum(int initial = 0) : d_sum(initial) { }
316///
317/// // MANIPULATORS
318///
319/// // Add the specified `v` to the running sum and return the running
320/// // sum.
321/// int operator()(int v)
322/// { return d_sum += v; }
323/// };
324/// @endcode
325/// Then, we test `myAlgorithm` with `RunningSum`:
326/// @code
327/// /// Test the user of `RunningSum` with `myAlgorithm`.
328/// bool testRunningSum()
329/// {
330/// myAlgorithm(testInput, testInput+DATA_SIZE, testOutput, RunningSum());
331///
332/// int sum = 0;
333/// for (std::size_t i = 0; i < DATA_SIZE; ++i) {
334/// sum += testInput[i];
335/// if (sum != testOutput[i]) {
336/// return false; // RETURN
337/// }
338/// }
339/// return true;
340/// }
341/// @endcode
342/// Note that `RunningSum::operator()` is a mutating operation and that, within
343/// `myAlgorithm`, `op` is const. Even though `bsl::function` owns a copy of
344/// its target, logical constness does not apply, as per the standard.
345///
346/// Finally, we run our tests and validate the results:
347/// @code
348/// void main()
349/// {
350/// assert(testNegation());
351/// assert(testRunningSum());
352/// }
353/// @endcode
354///
355/// ### Example 3: A Parallel Work queue {#bslstl_function-example-3-a-parallel-work-queue}
356///
357///
358/// In this example, we'll simulate a simple library whereby worker threads take
359/// work items from a queue and execute them asynchronously. This simulation is
360/// single-threaded, but keeps metrics on how much work each worker accomplished
361/// so that we can get a rough idea of how much parallelism was expressed by the
362/// program.
363///
364/// We start by defining a work item type to be stored in our work queue. This
365/// type is simply a `bsl::function` taking a `WorkQueue` pointer argument and
366/// returning `void`.
367/// @code
368/// class WorkQueue; // Forward declaration
369///
370/// typedef bsl::function<void(WorkQueue *)> WorkItem;
371/// @endcode
372/// Next, we define a work queue class. For simplicity, we'll implement our
373/// queue as a fixed-sized circular buffer and (because this is a
374/// single-threaded simulation), ignore synchronization concerns.
375/// @code
376/// /// A FIFO queue of tasks to be executed.
377/// class WorkQueue {
378///
379/// // PRIVATE CONSTANTS
380/// static const int k_MAX_ITEMS = 16;
381///
382/// // DATA
383/// int d_numItems;
384/// int d_head;
385/// WorkItem d_items[k_MAX_ITEMS];
386///
387/// public:
388/// // CREATORS
389///
390/// /// Create an empty work queue.
391/// WorkQueue()
392/// : d_numItems(0), d_head(0) { }
393///
394/// // MANIPULATORS
395///
396/// /// Move the work item at the head of the queue into the specified
397/// /// `result` and remove it from the queue. The behavior is
398/// /// undefined if this queue is empty.
399/// void dequeue(WorkItem *result)
400/// {
401/// assert(d_numItems > 0);
402/// *result = bslmf::MovableRefUtil::move(d_items[d_head]);
403/// d_head = (d_head + 1) % k_MAX_ITEMS; // circular
404/// --d_numItems;
405/// }
406///
407/// /// Enqueue the specified `item` work item onto the tail of the
408/// /// queue. The work is moved from `item`.
409/// void enqueue(bslmf::MovableRef<WorkItem> item)
410/// {
411/// int tail = (d_head + d_numItems++) % k_MAX_ITEMS; // circular
412/// assert(d_numItems <= k_MAX_ITEMS);
413/// d_items[tail] = bslmf::MovableRefUtil::move(item);
414/// }
415///
416/// // ACCESSORS
417///
418/// /// Return true if there are no items in the queue; otherwise return
419/// /// false.
420/// bool isEmpty() const { return 0 == d_numItems; }
421///
422/// /// Return the number of items currently in the queue.
423/// int size() const { return d_numItems; }
424/// };
425/// @endcode
426/// Next, we'll create a worker class that represents the state of a worker
427/// thread:
428/// @code
429/// /// A simulated worker thread.
430/// class Worker {
431///
432/// // DATA
433/// bool d_isIdle; // True if the worker is idle
434///
435/// public:
436/// // CREATORS
437///
438/// /// Create an idle worker.
439/// Worker()
440/// : d_isIdle(true) { }
441///
442/// // MANIPULATORS
443///
444/// /// Dequeue a task from the specified `queue` and execute it
445/// /// (asynchronously, in theory). The behavior is undefined unless
446/// /// this worker is idle before the call to `run`.
447/// void run(WorkQueue *queue);
448///
449/// // ACCESSORS
450///
451/// /// Return whether this worker is idle. An idle worker is one that
452/// /// can except work.
453/// bool isIdle() const { return d_isIdle; }
454/// };
455/// @endcode
456/// Next, we implement the `run` function, which removes a `bsl::function`
457/// object from the work queue and then executes it, passing the work queue as
458/// the sole argument:
459/// @code
460/// void Worker::run(WorkQueue *queue)
461/// {
462/// if (queue->isEmpty()) {
463/// // No work to do
464/// return; // RETURN
465/// }
466///
467/// WorkItem task;
468/// queue->dequeue(&task);
469///
470/// d_isIdle = false; // We're about to do work.
471/// task(queue); // Do the work.
472/// d_isIdle = true; // We're idle again.
473/// }
474/// @endcode
475/// Now, we implement a simple scheduler containing a work queue and an array of
476/// four workers, which are run in a round-robin fashion:
477/// @code
478/// /// Parallel work scheduler.
479/// class Scheduler {
480///
481/// // PRIVATE CONSTANTS
482/// static const int k_NUM_WORKERS = 4;
483///
484/// // DATA
485/// WorkQueue d_workQueue;
486/// Worker d_workers[k_NUM_WORKERS];
487///
488/// public:
489/// // CREATORS
490///
491/// /// Create a scheduler and enqueue the specified `initialTask`.
492/// explicit Scheduler(bslmf::MovableRef<WorkItem> initialTask)
493/// {
494/// d_workQueue.enqueue(bslmf::MovableRefUtil::move(initialTask));
495/// }
496///
497/// // MANIPULATORS
498///
499/// /// Execute the tasks in the work queue (theoretically in parallel)
500/// /// until the queue is empty.
501/// void run();
502/// };
503/// @endcode
504/// Next, we implement the scheduler's `run` method: which does a round-robin
505/// scheduling of the workers, allowing each to pull work off of the queue and
506/// run it. As tasks are run, they may enqueue more work. The scheduler
507/// returns when there are no more tasks in the queue.
508/// @code
509/// void Scheduler::run()
510/// {
511/// while (! d_workQueue.isEmpty()) {
512/// for (int i = 0; i < k_NUM_WORKERS; ++i) {
513/// if (d_workers[i].isIdle()) {
514/// d_workers[i].run(&d_workQueue);
515/// }
516/// }
517/// }
518/// }
519/// @endcode
520/// Next, we create a job for the parallel system to execute. A popular
521/// illustration of parallel execution is the quicksort algorithm, which is a
522/// recursive algorithm whereby the input array is partitioned into a low and
523/// high half and quicksort is recursively applied, in parallel, to the two
524/// halves. We define a class that encapsulates an invocation of quicksort on
525/// an input range:
526/// @code
527/// /// A functor class to execute parallel quicksort on a contiguous range
528/// /// of elements of specified `TYPE` supplied at construction.
529/// template <class TYPE>
530/// class QuickSortTask {
531///
532/// // DATA
533/// TYPE *d_begin_p;
534/// TYPE *d_end_p;
535///
536/// // PRIVATE CLASS METHODS
537///
538/// /// Partition the contiguous range specified by `[begin, end)` and
539/// /// return an iterator, `mid`, such that every element in the range
540/// /// `[begin, mid)` is less than `*mid` and every element in the
541/// /// range `[mid + 1, end)` is not less than `*mid`. The behavior is
542/// /// undefined unless `begin < end`.
543/// static TYPE* partition(TYPE *begin, TYPE *end);
544///
545/// public:
546/// // CREATORS
547///
548/// /// Create a task to sort the contiguous range from the item at the
549/// /// specified `begin` location up to but not included the item at
550/// /// the specified `end` location.
551/// QuickSortTask(TYPE *begin, TYPE *end)
552/// : d_begin_p(begin), d_end_p(end) { }
553///
554/// // MANIPULATORS
555///
556/// /// Preform the sort in parallel using the specified `queue` to
557/// /// enqueue parallel work.
558/// void operator()(WorkQueue *queue);
559/// };
560/// @endcode
561/// Next we implement the `partition` method, using a variation of the Lomuto
562/// partition scheme:
563/// @code
564/// template <class TYPE>
565/// TYPE* QuickSortTask<TYPE>::partition(TYPE *begin, TYPE *end)
566/// {
567/// using std::swap;
568///
569/// swap(begin[(end - begin) / 2], end[-1]); // Put pivot at end
570/// TYPE& pivot = *--end;
571/// TYPE *divider = begin;
572/// for (; begin != end; ++begin) {
573/// if (*begin < pivot) {
574/// swap(*divider, *begin);
575/// ++divider;
576/// }
577/// }
578/// swap(*divider, pivot); // Put pivot in the middle
579/// return divider;
580/// }
581/// @endcode
582/// Then we define the call operator for our task type, which performs the
583/// quicksort:
584/// @code
585/// template <class TYPE>
586/// void QuickSortTask<TYPE>::operator()(WorkQueue *queue)
587/// {
588/// if (d_end_p - d_begin_p < 2) {
589/// // Zero or one element. End recursion.
590/// return; // RETURN
591/// }
592///
593/// // Partition returns end iterator for low partition == begin iterator
594/// // for high partition.
595/// TYPE *mid = partition(d_begin_p, d_end_p);
596///
597/// // Asynchronously sort the two partitions
598/// WorkItem sortLoPart(QuickSortTask(d_begin_p, mid));
599/// WorkItem sortHiPart(QuickSortTask(mid + 1, d_end_p));
600/// queue->enqueue(bslmf::MovableRefUtil::move(sortLoPart));
601/// queue->enqueue(bslmf::MovableRefUtil::move(sortHiPart));
602/// }
603/// @endcode
604/// Finally, we use our scheduler and our `QuickSortTask` to sort an array
605/// initially containing the integers between 1 and 31 in random order:
606/// @code
607/// void main()
608/// {
609/// short data[] = {
610/// 23, 12, 2, 28, 1, 10, 5, 13, 15, 8, 19, 14, 31, 29, 9, 11, 24, 3,
611/// 30, 7, 17, 27, 20, 21, 18, 4, 22, 25, 16, 6, 26
612/// };
613///
614/// static const int DATA_SIZE = sizeof(data) / sizeof(data[0]);
615///
616/// WorkItem initialTask(QuickSortTask<short>(data, data + DATA_SIZE));
617/// Scheduler sched(bslmf::MovableRefUtil::move(initialTask));
618/// sched.run();
619///
620/// // Validate results
621/// for (int i = 0; i < DATA_SIZE; ++i) {
622/// assert(i + 1 == data[i]);
623/// }
624/// }
625/// @endcode
626/// @}
627/** @} */
628/** @} */
629
630/** @addtogroup bsl
631 * @{
632 */
633/** @addtogroup bslstl
634 * @{
635 */
636/** @addtogroup bslstl_function
637 * @{
638 */
639
640#include <bslscm_version.h>
641
642#include <bslma_allocator.h>
643#include <bslma_bslallocator.h>
645
646#include <bslmf_allocatorargt.h>
647#include <bslmf_assert.h>
648#include <bslmf_forwardingtype.h>
649#include <bslmf_isintegral.h>
650#include <bslmf_movableref.h>
653#include <bslmf_util.h> // 'forward(V)'
654
655#include <bsls_assert.h>
656#include <bsls_buildtarget.h>
659#include <bsls_exceptionutil.h>
660#include <bsls_keyword.h>
661#include <bsls_nullptr.h>
662#include <bsls_platform.h>
663#include <bsls_unspecifiedbool.h>
664#include <bsls_util.h> // 'forward<T>(V)'
665
666#ifdef BDE_BUILD_TARGET_EXC
668#endif
669#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
670#include <bslstl_pair.h>
671#endif
673
674// Sub-components:
675#ifdef BSLSTL_FUNCTION_VARIADIC_LIMIT
676#define BSLSTL_FUNCTION_INVOKERUTIL_VARIADIC_LIMIT \
677 BSLSTL_FUNCTION_VARIADIC_LIMIT
678#endif
681#include <bslstl_function_rep.h>
683
684#include <cstddef>
685#include <cstdlib>
686#include <typeinfo>
687#include <utility>
688
689#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
690#include <stdlib.h> // Import global-scope 'abs(double)'
691#endif
692
693#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
694// Include version that can be compiled with C++03
695// Generated on Thu Oct 21 10:11:37 2021
696// Command line: sim_cpp11_features.pl bslstl_function.h
697# define COMPILING_BSLSTL_FUNCTION_H
698# include <bslstl_function_cpp03.h>
699# undef COMPILING_BSLSTL_FUNCTION_H
700#else
701
702// 'BSLS_ASSERT' filename fix -- See @ref bsls_assertimputil
703#ifdef BSLS_ASSERTIMPUTIL_AVOID_STRING_CONSTANTS
704
705extern const char s_bslstl_function_h[];
706#undef BSLS_ASSERTIMPUTIL_FILE
707#define BSLS_ASSERTIMPUTIL_FILE BloombergLP::s_bslstl_function_h
708
709#endif
710
711// FORWARD DECLARATIONS
712namespace bsl {
713
714/// Forward declaration.
715template <class PROTOTYPE>
716class function;
717
718} // close namespace bsl
719
720
721
722#ifndef BDE_OMIT_INTERNAL_DEPRECATED
723
724/// Forward declaration of legacy `bdef_Function` in order to implement
725/// by-reference conversion from `bsl::function<F>`. This declaration
726/// produces a by-name cyclic dependency between `bsl` and `bde` in order to
727/// allow legacy code to transition to `bsl::function` from (the deprecated)
728/// `bdef_Function`. The conversion, and therefore this forward reference,
729/// should not appear in the open-source version of this component.
730template <class PROTOTYPE>
732
733#endif // BDE_OMIT_INTERNAL_DEPRECATED
734
735namespace bslstl {
736
737 // =================================
738 // struct template Function_ArgTypes
739 // =================================
740
741/// This component-private struct template provides the following nested
742/// typedefs for `bsl::function` for a specified `PROTOTYPE` which must be a
743/// function type:
744/// @code
745/// argument_type -- Only if PROTOTYPE takes exactly one argument
746/// first_argument_type -- Only if PROTOTYPE takes exactly two arguments
747/// second_argument_type -- Only if PROTOTYPE takes exactly two arguments
748/// @endcode
749/// The C++ Standard requires that `function` define these typedefs for
750/// compatibility with one- and two-argument legacy (now deprecated) functor
751/// adaptors. `bsl::function` publicly inherits from an instantiation of
752/// this template in order to conditionally declare the above nested types.
753/// This primary (unspecialized) template provides no typedefs.
754template <class PROTOTYPE>
756};
757
758/// This component-private specialization of `Function_ArgTypes` is for
759/// function prototypes that take exactly one argument and provides an
760/// `argument_type` nested typedef.
761template <class RET, class ARG>
762struct Function_ArgTypes<RET(ARG)> {
763
764 // PUBLIC TYPES
766 "deprecated_cpp17_standard_library_features",
767 "do not use")
768 /// @deprecated This typedef is deprecated in C++17, for details see
769 /// https://isocpp.org/files/papers/p0005r4.html.
770 typedef ARG argument_type;
771};
772
773/// This component-private specialization of `Function_ArgTypes` is for
774/// functions that take exactly two arguments and provides
775/// `first_argument_type` and `second_argument_type` nested typedefs.
776template <class RET, class ARG1, class ARG2>
777struct Function_ArgTypes<RET(ARG1, ARG2)> {
778
779 // PUBLIC TYPES
781 "deprecated_cpp17_standard_library_features",
782 "do not use")
783 /// @deprecated This typedef is deprecated in C++17, for details see
784 /// https://isocpp.org/files/papers/p0005r4.html.
785 typedef ARG1 first_argument_type;
786
788 "deprecated_cpp17_standard_library_features",
789 "do not use")
790 /// @deprecated This typedef is deprecated in C++17, for details see
791 /// https://isocpp.org/files/papers/p0005r4.html.
792 typedef ARG2 second_argument_type;
793};
794
795 // ================================
796 // class template Function_Variadic
797 // ================================
798
799#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
800
801template <class PROTOTYPE>
802class Function_Variadic; // Primary template is never instantiated
803
804/// This component-private class template contains the physical
805/// representation and provides the variadic interfaces for `bsl::function`
806/// (see class and component documentation for `bsl::function`).
807/// `bsl::function` publicly inherits from an instantiation of this
808/// template. This implementation class exists to 1) minimize the amount of
809/// variadic template expansion required in C++03 using the
810/// `sim_cpp11_features.pl` utility and 2) work around issues with the Sun
811/// CC compiler, which has trouble with argument type deduction when a
812/// template argument has a partial specialization (as `Function_Variadic`
813/// does). `bsl::function` does not have a partial specialization and
814/// delegates to the `Function_Variadic` base class only those parts of the
815/// interface and implementation that depend on decomposing the function
816/// prototype into a return type and variadic list of argument types.
817template <class RET, class... ARGS>
818class Function_Variadic<RET(ARGS...)> : public Function_ArgTypes<RET(ARGS...)>
819{
820
821 // PRIVATE TYPES
823
824 /// Type of invocation function. A generic function pointer is stored
825 /// in the representation and is cast to this type to invoke the
826 /// specific type of target stored in this wrapper.
827 typedef RET Invoker(const Function_Rep *,
829
830 // 'protected' to workaround a Sun bug when instantiating 'bsl::function'
831 // implicitly from an 'extern "C"' function pointer, e.g. in a 'bind'
832 // expression.
833 protected:
834 // DATA
835 Function_Rep d_rep; // Non-templated representation
836
837 private:
838 // NOT IMPLEMENTED
840
841 /// This component-private base class is not directly copyable.
844
845 // FRIENDS
846 friend class bsl::function<RET(ARGS...)>;
847
848 public:
849 // PUBLIC TYPES
850 typedef RET result_type;
852
853 // CREATORS
854
855 /// Create an empty object. Use the specified `allocator` (e.g., the
856 /// address of a `bslma::Allocator`) to supply memory.
857 Function_Variadic(const allocator_type& allocator);
858
860 // // Destroy this object and its target object.
861
862 // MANIPULATORS
863
864 /// If this object is empty, throw `bsl::bad_function_call`; otherwise
865 /// invoke the target object with the specified `args...` and return the
866 /// result (after conversion to `RET`). Note that, even though it is
867 /// declared `const`, this call operator can mutate the target object
868 /// and is thus considered a manipulator rather than an accessor.
869 RET operator()(ARGS... args) const;
870};
871
872#endif
873
874 // =================================================
875 // struct template Function_IsInvocableWithPrototype
876 // =================================================
877
878/// Forward declaration of the component-private
879/// `Function_IsInvocableWithPrototype` `struct` template. The primary
880/// (unspecialized) template is not defined. This `struct` template
881/// implements a boolean metafunction that publicly inherits from
882/// `bsl::true_type` if an object of the specified `FUNC` type is invocable
883/// under the specified `PROTOTYPE`, and inherits from `bsl::false_type`
884/// otherwise. An object of `FUNC` type is invocable under the `PROTOTYPE`
885/// if it is Lvalue-Callable with the arguments of the `PROTOTYPE`, and
886/// returns an object of type convertible to the return type of the
887/// `PROTOTYPE`. If the return type of the `PROTOTYPE` is `void`, then any
888/// type is considered convertible to the return type of the `PROTOTYPE`.
889/// In C++03, `FUNC` is considered Lvalue-Callable with the argument and
890/// return types of the `PROTOTYPE` if it is not an integral type. This
891/// `struct` template requires 'PROTOTYPE" to be an unqualified function
892/// type.
893template <class PROTOTYPE, class FUNC>
895
896} // close package namespace
897
898
899namespace bsl {
900
901 // =======================
902 // class template function
903 // =======================
904
905/// This class template implements the C++ Standard Library `std::function`
906/// template, enhanced for allocator support as per Standards Proposal
907/// P0987. An instantiation of this template generalizes the notion of a
908/// pointer to a function having the specified `PROTOTYPE` expressed as a
909/// function type (e.g., `int(const char *, float)`). An object of this
910/// class wraps a copy of the callable object specified at construction (if
911/// any), such as a function pointer, member-function pointer, member-data
912/// pointer, or functor object. The wrapped object (called the *target* or
913/// *target* *object*) is owned by the `bsl::function` object (unlike the
914/// function pointer that it mimics). Invoking the `bsl::function` object
915/// will invoke the target (or throw an exception, if there is no target).
916/// Note that `function` will compile only if `PROTOTYPE` is a function
917/// type.
918///
919/// To optimize away many heap allocations, objects of this type have a
920/// buffer into which small callable objects can be stored. In order to
921/// qualify for this small-object optimization, a callable type must not
922/// only fit in the buffer but must also be nothrow move constructible. The
923/// latter constraint allows this type to be nothrow move constructible and
924/// nothrow swappable, as required by the C++ Standard. The small object
925/// buffer is guaranteed to be large enough to hold a pointer to function,
926/// pointer to member function, pointer to member data, a
927/// `bsl::reference_wrapper`, or an empty struct. Although the standard
928/// does not specify a minimum size beyond the aforementioned guarantee,
929/// many small structs will fit in the small object buffer, as defined in
930/// the `bslstl_function_smallobjectoptimization` component.
931///
932/// See @ref bslstl_function
933template <class PROTOTYPE>
934class function : public BloombergLP::bslstl::Function_Variadic<PROTOTYPE> {
935
936 private:
937 // PRIVATE TYPES
938 typedef BloombergLP::bslstl::Function_Variadic<PROTOTYPE> Base;
939 typedef BloombergLP::bslstl::Function_Rep Function_Rep;
940 typedef BloombergLP::bslmf::MovableRefUtil MovableRefUtil;
941
942 /// Abbreviation for metafunction that determines whether a reference
943 /// from `FROM` can be cast to a reference to `TO` without loss of
944 /// information.
945 template <class FROM, class TO>
946 struct IsReferenceCompatible
947 : BloombergLP::bslstl::Function_IsReferenceCompatible<FROM, TO>::type {
948 };
949
950 /// Abbreviation for metafunction used to provide a C++03-compatible
951 /// implementation of `std::decay` that treats `bslmf::MovableReference`
952 /// as an rvalue reference.
953 template <class TYPE>
954 struct Decay : MovableRefUtil::Decay<TYPE> {
955 };
956
957 /// Abbreviation for a metafunction used to determine whether an object
958 /// of the specified `FUNC` is callable with argument types of the
959 /// specified `PROTOTYPE` and returns a type convertible to the return
960 /// type of the `PROTOTYPE`.
961 template <class FUNC>
962 struct IsInvocableWithPrototype
963 : BloombergLP::bslstl::Function_IsInvocableWithPrototype<PROTOTYPE, FUNC> {
964 };
965
966#ifndef BSLS_COMPILERFEATURES_SUPPORT_OPERATOR_EXPLICIT
967 /// Unique type that evaluates to true or false in a boolean control
968 /// construct such as an `if` or `while` statement. In C++03,
969 /// `function` is implicitly convertible to this type but is not
970 /// implicitly convertible to `bool`. In C++11 and later, `function` is
971 /// explicitly convertible to `bool`, so this type is not needed.
972 typedef BloombergLP::bsls::UnspecifiedBool<function> UnspecifiedBoolUtil;
973 typedef typename UnspecifiedBoolUtil::BoolType UnspecifiedBool;
974
975 // NOT IMPLEMENTED
976
977 /// Since `function` does not support `operator==` and `operator!=`,
978 /// they must be deliberately suppressed; otherwise `function` objects
979 /// would be implicitly comparable by implicit conversion to
980 /// `UnspecifiedBool`.
981 bool operator==(const function&) const; // Declared but not defined
982 bool operator!=(const function&) const; // Declared but not defined
983#endif // !defined(BSLS_COMPILERFEATURES_SUPPORT_OPERATOR_EXPLICIT)
984
985 // PRIVATE MANIPULATORS
986
987 /// Set the target of this `function` by constructing from the specified
988 /// `func` callable object. If the type of `func` is a movable
989 /// reference, then the target is constructed by extended move
990 /// construction; otherwise by extended copy construction.
991 /// Instantiation will fail unless `FUNC` is a callable type that is
992 /// invocable with arguments in `PROTOTYPE` and yields a return type
993 /// that is convertible to the return type in `PROTOTYPE`.
994 template <class FUNC>
995 void installFunc(BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func);
996
997 public:
998 // TRAITS
1000 BloombergLP::bslma::UsesBslmaAllocator);
1002 BloombergLP::bslmf::UsesAllocatorArgT);
1005
1006 // TYPES
1007 typedef Function_Rep::allocator_type allocator_type;
1008
1009 // CREATORS
1012 function(allocator_arg_t ,
1014
1015 /// Create an empty `function` object. Optionally specify an
1016 /// `allocator` (e.g., the address of a `bslma::Allocator` object) to
1017 /// supply memory; otherwise, the default allocator is used.
1018 function(allocator_arg_t ,
1021
1022 /// Create an object wrapping the specified `func` callable object. Use
1023 /// the default allocator to supply memory. If `func` is a null pointer
1024 /// or null pointer-to-member, then the resulting object will be empty.
1025 /// This constructor will not participate in overload resolution if
1026 /// `func` is of the same type as (or reference compatible with) this
1027 /// object (to avoid ambiguity with the copy and move constructors) or
1028 /// is an integral type (to avoid matching null pointer literals). In
1029 /// C++03, this function will not participate in overload resolution if
1030 /// `FUNC` is a `MovableRef` (see overload, below), and instantiation
1031 /// will fail unless `FUNC` is invocable using the arguments and return
1032 /// type specified in `PROTOTYPE`. In C++11 and later, this function
1033 /// will not participate in overload resolution if `FUNC` is not
1034 /// invocable using the arguments and return type specified in
1035 /// `PROTOTYPE`. Note that this constructor implicitly converts from
1036 /// any type that is so invocable.
1037 template <class FUNC>
1039 typename enable_if<
1040 ! IsReferenceCompatible<typename Decay<FUNC>::type,
1041 function>::value
1042 && IsInvocableWithPrototype<
1043 typename Decay<FUNC>::type>::value
1044#ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1045 && ! MovableRefUtil::IsMovableReference<FUNC>::value
1046#endif
1047#ifdef BSLS_PLATFORM_CMP_IBM
1049#endif
1050 , int>::type = 0)
1051 : Base(allocator_type())
1052 {
1053 ///Implementation Note
1054 ///- - - - - - - - - -
1055 // The body of this constructor must be inlined inplace because the use
1056 // of 'enable_if' will otherwise break the MSVC 2010 compiler.
1057 //
1058 // The `! bsl::is_function<FUNC>::value` constraint is required in
1059 // C++03 mode when using the IBM XL C++ compiler. In C++03,
1060 // `BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func` expands to
1061 // `const FUNC& func`. A conforming compiler deduces a
1062 // reference-to-function type for `func` when it binds to a function
1063 // argument. The IBM XL C++ compiler erroneously does not collapse the
1064 // `const` qualifier when `FUNC` is deduced to be a function type, and
1065 // instead attempts to deduce the type of `func` to be a reference to a
1066 // `const`-qualified function. This causes substitution to fail
1067 // because function-typed expressions are never `const`. This
1068 // component solves the problem by accepting a `func` having a function
1069 // type as a pointer to a (non-`const`) function. An overload for the
1070 // corresponding constructor is defined below.
1071
1072 installFunc(BSLS_COMPILERFEATURES_FORWARD(FUNC, func));
1073 }
1074
1075#ifdef BSLS_PLATFORM_CMP_IBM
1076 template <class FUNC>
1077 function(FUNC *func, // IMPLICIT
1078 typename enable_if<is_function<FUNC>::value, int>::type = 0)
1079
1080 : Base(allocator_type())
1081 {
1082 ///Implementation Note
1083 ///- - - - - - - - - -
1084 // This constructor overload only exists to work around an IBM XL C++
1085 // compiler defect. See the implementation notes for the above
1086 // constructor overload for more information.
1087 //
1088 // This constructor also forwards the `func` as a pointer-to-function
1089 // type to downstream operations in order to work around the
1090 // aforementioned reference-to-function type deduction defects.
1091 //
1092 // Further, note that instantiation of this constructor will fail
1093 // unless `FUNC` is invocable using the arguments and return type
1094 // specified in `PROTOTYPE`. This component assumes that the IBM XL
1095 // C++ compiler does not support C++11 or later.
1096
1097 installFunc(func);
1098 }
1099#endif
1100
1101#ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1102 /// Create an object wrapping the specified `func` callable object.
1103 /// This constructor (ctor 2) is identical to the previous constructor
1104 /// (ctor 1) except that, in C++03 ctor 2 provides for explicit
1105 /// construction from a `MovableRef` referencing a callable type, rather
1106 /// than an implicit conversion for `FUNC` not being a `MovableRef`. In
1107 /// C++11, overload resolution matching an argument of type `T&&` to a
1108 /// parameter of type `T` (exact match) is always preferred over
1109 /// matching `T&&` to `bsl::function` (conversion). In C++03, however
1110 /// `MovableRef` is not a real reference type, so it sometimes creates
1111 /// overload ambiguities whereby matching `MovableRef<T>` to `T`
1112 /// (conversion) is no better than matching `MovableRef<T>` to
1113 /// `bsl::function` (also conversion). This ambiguity is resolved by
1114 /// making this constructor from `MovableRef<T>` explicit, while leaving
1115 /// other constructor from `FUNC` implicit. This means that
1116 /// `move` will fail in a narrow set of cases in C++03, as shown below:
1117 /// @code
1118 /// typedef bsl::function<void(int)> Obj;
1119 /// MyCallableType x;
1120 ///
1121 /// Obj f1 = x; // OK
1122 /// Obj f2 = bslmf::MovableRefUtil::move(x); // No conversion in C++03
1123 /// Obj f3(bslmf::MovableRefUtil::move(x)); // OK, normal ctor call
1124 ///
1125 /// void y(const Obj& f);
1126 /// y(x); // OK
1127 /// y(bslmf::MovableRefUtil::move(x)); // Not found in C++03
1128 /// y(Obj(bslmf::MovableRefUtil::move(x))); // OK, explicit cast
1129 /// @endcode
1130 /// As you can see from the examples above, there are simple workarounds
1131 /// for the problem cases, although generic code might need to be extra
1132 /// careful.
1133 template <class FUNC>
1134 explicit function(const BloombergLP::bslmf::MovableRef<FUNC>& func,
1135 typename enable_if<
1136 ! IsReferenceCompatible<typename Decay<FUNC>::type,
1137 function>::value
1138 && IsInvocableWithPrototype<
1139 typename Decay<FUNC>::type>::value
1140 , int>::type = 0)
1141 : Base(allocator_type())
1142 {
1143 ///Implementation Note
1144 ///- - - - - - - - - -
1145 // The body of this constructor must inlined inplace because the use of
1146 // `enable_if` will otherwise break the MSVC 2010 compiler.
1147
1148 installFunc(BloombergLP::bslmf::MovableRefUtil::move(func));
1149 }
1150#endif
1151
1152 /// Create an object wrapping the specified `func` callable object. Use
1153 /// the specified `allocator` (i.e., the address of a `bslma::Allocator`
1154 /// object) to supply memory. If `func` is a null pointer or null
1155 /// pointer-to-member, then the resulting object will be empty. This
1156 /// constructor will not participate in overload resolution if `func` is
1157 /// of the same type as (or reference compatible with) this object (to
1158 /// avoid ambiguity with the extended copy and move constructors) or is
1159 /// an integral type (to avoid matching null pointer literals). In
1160 /// C++03, this function will not participate in overload resolution if
1161 /// `FUNC` is a `MovableRef` (see overload, below), and instantiation
1162 /// will fail unless `FUNC` is invocable using the arguments and return
1163 /// type specified in `PROTOTYPE`. In C++11 and later, this function
1164 /// will not participate in overload resolution if `FUNC` is not
1165 /// invocable using the arguments and return type specified in
1166 /// `PROTOTYPE`. Note that this constructor implicitly converts from
1167 /// any type that is so invocable.
1168 template <class FUNC>
1169 function(allocator_arg_t,
1172 typename enable_if<
1173 ! IsReferenceCompatible<typename Decay<FUNC>::type,
1174 function>::value
1175 && IsInvocableWithPrototype<
1176 typename Decay<FUNC>::type>::value
1177#ifdef BSLS_PLATFORM_CMP_IBM
1179#endif
1180 , int>::type = 0)
1181 : Base(allocator)
1182 {
1183 ///Implementation Note
1184 ///- - - - - - - - - -
1185 // The body of this constructor must inlined inplace because the use of
1186 // `enable_if` will otherwise break the MSVC 2010 compiler.
1187 //
1188 // The `! bsl::is_function<FUNC>::value` constraint is required in
1189 // C++03 mode when using the IBM XL C++ compiler. In C++03,
1190 // `BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func` expands to
1191 // `const FUNC& func`. A conforming compiler deduces a
1192 // reference-to-function type for `func` when it binds to a function
1193 // argument. The IBM XL C++ compiler erroneously does not collapse the
1194 // `const` qualifier when `FUNC` is deduced to be a function type, and
1195 // instead attempts to deduce the type of `func` to be a reference to a
1196 // `const`-qualified function. This causes substitution to fail
1197 // because function-typed expressions are never `const`. This
1198 // component solves the problem by accepting a `func` having a function
1199 // type as a pointer to a (non-`const`) function. An overload for the
1200 // corresponding constructor is defined below.
1201
1202 installFunc(BSLS_COMPILERFEATURES_FORWARD(FUNC, func));
1203 }
1204
1205#ifdef BSLS_PLATFORM_CMP_IBM
1206 template <class FUNC>
1207 function(allocator_arg_t,
1208 const allocator_type& allocator,
1209 FUNC *func,
1210 typename enable_if<is_function<FUNC>::value, int>::type = 0)
1211 : Base(allocator)
1212 {
1213 ///Implementation Note
1214 ///- - - - - - - - - -
1215 // This constructor overload only exists to work around an IBM XL C++
1216 // compiler defect. See the implementation notes for the above
1217 // constructor overload for more information.
1218 //
1219 // This constructor also forwards the `func` as a pointer-to-function
1220 // type to downstream operations in order to work around the
1221 // aforementioned reference-to-function type deduction defects.
1222 //
1223 // Further, note that instantiation of this constructor will fail
1224 // unless `FUNC` is invocable using the arguments and return type
1225 // specified in `PROTOTYPE`. This component assumes that the IBM XL
1226 // C++ compiler does not support C++11 or later.
1227
1228 installFunc(func);
1229 }
1230#endif
1231
1232 function(const function& original);
1233 /// Create a `function` having the same value as (i.e., wrapping a copy
1234 /// of the target held by) the specified `original` object. Optionally
1235 /// specify an `allocator` (e.g., the address of a `bslma::Allocator`
1236 /// object) to supply memory; otherwise, the default allocator is used.
1237 function(allocator_arg_t ,
1239 const function& original);
1240
1241 /// Create a `function` having the same target as the specified
1242 /// `original` object. Use `original.get_allocator()` as the allocator
1243 /// to supply memory. The `original` object is set to empty after the
1244 /// new object is created. If the target qualifies for the small-object
1245 /// optimization (see class-level documentation), then it is
1246 /// move-constructed into the new object; otherwise ownership of the
1247 /// target is transferred without using the target's move constructor.
1248 function(BloombergLP::bslmf::MovableRef<function> original)
1249 BSLS_KEYWORD_NOEXCEPT; // IMPLICIT
1250
1251 /// Create a `function` having the same value as (i.e., wrapping a copy
1252 /// of the target held by) the specified `original` object. Use the
1253 /// specified `allocator` (e.g., the address of a `bslma::Allocator`
1254 /// object) to supply memory. If `allocator == original.allocator()`,
1255 /// this object is created as if by move construction; otherwise it is
1256 /// created as if by extended copy construction using `allocator`.
1257 function(allocator_arg_t ,
1259 BloombergLP::bslmf::MovableRef<function> original);
1260
1261 // MANIPULATORS
1262
1263 /// Set the target of this object to a copy of the target (if any)
1264 /// held by the specified `rhs` object, destroy the target (if any)
1265 /// previously held by `*this`, and return `*this`. The result is
1266 /// equivalent to having constructed `*this` from `rhs` using the
1267 /// extended copy constructor with allocator `this->get_allocator()`.
1268 /// If an exception is thrown, `*this` is not modified (i.e., copy
1269 /// assignment provides the strong exception guarantee).
1271
1272 /// Set the target of this object to the target (if any) held by the
1273 /// specified `rhs` object, destroy the target (if any) previously held
1274 /// by `*this`, and return `*this`. The result is equivalent to having
1275 /// constructed `*this` from `rhs` using the extended move constructor
1276 /// with allocator `this->get_allocator()`. If an exception is thrown,
1277 /// `rhs` will have a valid but unspecified value and `*this` will not
1278 /// be modified. Note that an exception will never be thrown if
1279 /// `get_allocator() == rhs.get_allocator()`.
1280 function& operator=(BloombergLP::bslmf::MovableRef<function> rhs);
1281
1282 /// Set the target of this object to the specified `rhs` callable
1283 /// object, destroy the previous target (if any), and return `*this`.
1284 /// The result is equivalent to having constructed `*this` from
1285 /// `std::forward<FUNC>(rhs)` and `this->get_allocator()`. Note that
1286 /// this assignment operator will not participate in overload resolution
1287 /// if `func` is of the same type as this object (to avoid ambiguity
1288 /// with the copy and move assignment operators.) In C++03,
1289 /// instantiation will fail unless `FUNC` is invocable with the
1290 /// arguments and return type specified in `PROTOTYPE`. In C++11 and
1291 /// later, this assignment operator will not participate in overload
1292 /// resolution unless `FUNC` is invocable with the arguments and return
1293 /// type specified in `PROTOTYPE`.
1294 template <class FUNC>
1295 typename enable_if<
1296 ! IsReferenceCompatible<typename Decay<FUNC>::type, function>::value
1297 && IsInvocableWithPrototype<typename Decay<FUNC>::type>::value
1298 , function&>::type
1300 {
1301 ///Implementation Note
1302 ///- - - - - - - - - -
1303 // The body of this operator must inlined inplace because the use of
1304 // `enable_if` will otherwise break the MSVC 2010 compiler.
1305
1306 function(allocator_arg, this->get_allocator(),
1307 BSLS_COMPILERFEATURES_FORWARD(FUNC, rhs)).swap(*this);
1308 return *this;
1309 }
1310
1311#ifdef BSLS_PLATFORM_CMP_IBM
1312 /// Set the target of this object to the specified `rhs` function
1313 /// pointer. This overload exists only for the IBM compiler, which has
1314 /// trouble decaying functions to function pointers in
1315 /// pass-by-const-reference template arguments.
1316 template <class FUNC>
1318 operator=(FUNC *rhs)
1319 {
1320 ///Implementation Note
1321 ///- - - - - - - - - -
1322 // The body of this operator must inlined inplace.
1323 //
1324 // Further, note that instantiation of this assignment operator will
1325 // fail unless `FUNC` is invocable using the arguments and return type
1326 // specified in `PROTOTYPE`. This component assumes that the IBM XL
1327 // C++ compiler does not support C++11 or later.
1328
1329 function(allocator_arg, this->get_allocator(), rhs).swap(*this);
1330 return *this;
1331 }
1332#endif
1333
1334 /// Destroy the current target (if any) of this object, then set the
1335 /// target to the specified `rhs` wrapper containing a reference to a
1336 /// callable object and return `*this`. The result is equivalent to
1337 /// having constructed `*this` from `rhs` and `this->get_allocator()`.
1338 /// Note that this assignment is a separate overload only because it is
1339 /// unconditionally `noexcept`.
1340 template <class FUNC>
1341 typename enable_if<
1342 IsInvocableWithPrototype<typename Decay<FUNC>::type>::value
1343 , function &>::type
1344 operator=(bsl::reference_wrapper<FUNC> rhs) BSLS_KEYWORD_NOEXCEPT
1345 {
1346 /// Implementation Note
1347 ///- - - - - - - - - -
1348 // The body of this operator must inlined inplace because the use of
1349 // 'enable_if' will otherwise break the MSVC 2010 compiler.
1350
1351 function(allocator_arg, this->get_allocator(), rhs).swap(*this);
1352 return *this;
1353 }
1354
1355 /// Set this object to empty and return `*this`.
1357
1358 // Inherit 'operator()' from 'Function_Variadic' base class.
1359
1360 /// If this object is empty, throw `bsl::bad_function_call`; otherwise
1361 /// invoke the target object with the specified `args...` and return the
1362 /// result (after conversion to `RET`). Note that, even though it is
1363 /// declared `const`, this call operator can mutate the target object
1364 /// and is thus considered a manipulator rather than an accessor.
1365 using Base::operator();
1366
1367 /// Exchange the targets held by this `function` and the specified
1368 /// `other` `function`. The behavior is undefined unless
1369 /// `get_allocator() == other.get_allocator()`.
1371
1372 /// If `TP` is the same type as the target object, returns a pointer
1373 /// granting modifiable access to the target; otherwise return a null
1374 /// pointer.
1375 template<class TP> TP* target() BSLS_KEYWORD_NOEXCEPT;
1376
1377 // ACCESSORS
1378#ifdef BSLS_COMPILERFEATURES_SUPPORT_OPERATOR_EXPLICIT
1379 /// (C++11 and later) Return false if this object is empty, otherwise
1380 /// return true. Note that this is an explicit conversion operator and
1381 /// is typically invoked implicitly in contexts such as in the condition
1382 /// of an `if` or `while` statement, though it can also be invoked via
1383 /// an explicit cast.
1384 explicit // Explicit conversion available only with C++11
1385 operator bool() const BSLS_KEYWORD_NOEXCEPT;
1386#else
1387 /// (C++03 only) Return a null value if this object is empty, otherwise
1388 /// an arbitrary non-null value. Note that this operator will be
1389 /// invoked implicitly in boolean contexts such as in the condition of
1390 /// an `if` or `while` statement, but does not constitute an implicit
1391 /// conversion to `bool`.
1392 operator UnspecifiedBool() const BSLS_KEYWORD_NOEXCEPT
1393 {
1394 // Inplace inlined to work around xlC bug when out-of-line.
1395 return UnspecifiedBoolUtil::makeValue(0 != this->d_rep.invoker());
1396 }
1397#endif
1398
1399 /// Return (a copy of) the allocator used to supply memory for this
1400 /// `function`.
1402
1403 /// If `TP` is the same type as the target object, returns a pointer
1404 /// granting read-only access to the target; otherwise return a null
1405 /// pointer.
1406 template<class TP> const TP* target() const BSLS_KEYWORD_NOEXCEPT;
1407
1408 /// Return `typeid(void)` if this object is empty; otherwise
1409 /// `typeid(FUNC)` where `FUNC` is the type of the target object.
1410 const std::type_info& target_type() const BSLS_KEYWORD_NOEXCEPT;
1411
1412#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1413 // LEGACY METHODS
1414
1415 /// @deprecated Use @ref bsl::function` instead of `bdef_Function.
1416 ///
1417 /// Return `*this`, converted to a mutable `bdef_Function` reference by
1418 /// downcasting. The behavior is undefined unless `bdef_Function<F*>`
1419 /// is derived from `bsl::function<F>` and adds no new data members.
1420 operator BloombergLP::bdef_Function<PROTOTYPE *>&() BSLS_KEYWORD_NOEXCEPT;
1421
1422 /// @deprecated Use @ref bsl::function` instead of `bdef_Function.
1423 ///
1424 /// Return `*this` converted to a const `bdef_Function` reference by
1425 /// downcasting. The behavior is undefined unless `bdef_Function<F*>`
1426 /// is derived from `bsl::function<F>` and adds no new data members.
1427 operator const BloombergLP::bdef_Function<PROTOTYPE *>&() const
1429
1430 // LEGACY ACCESSORS
1431
1432 /// @deprecated Use @ref get_allocator() instead.
1433 ///
1434 /// Return `get_allocator().mechanism()`. Note that this function
1435 /// exists for BDE compatibility and is not part of the C++ Standard
1436 /// Library.
1437 BloombergLP::bslma::Allocator *allocator() const BSLS_KEYWORD_NOEXCEPT;
1438
1439 /// @deprecated Runtime checking of this optimization is discouraged.
1440 ///
1441 /// Return `true` if this `function` is empty or if it is non-empty and
1442 /// its target qualifies for the small-object optimization (and is thus
1443 /// allocated within this object's footprint); otherwise, return false.
1444 bool isInplace() const BSLS_KEYWORD_NOEXCEPT;
1445#endif
1446};
1447
1448#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1449// CLASS TEMPLATE DEDUCTION GUIDES
1450
1451/// Deduce the template parameter `PROTOTYPE` from the signature of the
1452/// function supplied to the constructor of `function`.
1453template<class RET, class... ARGS>
1454function(RET(*)(ARGS...)) -> function<RET(ARGS...)>;
1455
1456/// Deduce the template parameter `PROTOTYPE` from the signature of the
1457/// function supplied to the constructor of `function`.
1458template<class ALLOC, class RET, class... ARGS>
1459function(allocator_arg_t, ALLOC, RET(*)(ARGS...)) -> function<RET(ARGS...)>;
1460
1461
1462/// This struct provides a set of template `meta-functions` that extract
1463/// the signature of a class member function, stripping any qualifiers such
1464/// as `const`, `noexcept` or `&`.
1465struct FunctionDeductionHelper {
1466
1467 public:
1468 // PUBLIC TYPES
1469 template<class FUNCTOR>
1470 struct StripSignature {};
1471
1472 template<class RET, class FUNCTOR, class ...ARGS>
1473 struct StripSignature<RET (FUNCTOR::*) (ARGS...)>
1474 { using Sig = RET(ARGS...); };
1475
1476 template<class RET, class FUNCTOR, class ...ARGS>
1477 struct StripSignature<RET (FUNCTOR::*) (ARGS...) const>
1478 { using Sig = RET(ARGS...); };
1479
1480 template<class RET, class FUNCTOR, class ...ARGS>
1481 struct StripSignature<RET (FUNCTOR::*) (ARGS...) noexcept>
1482 { using Sig = RET(ARGS...); };
1483
1484 template<class RET, class FUNCTOR, class ...ARGS>
1485 struct StripSignature<RET (FUNCTOR::*) (ARGS...) const noexcept>
1486 { using Sig = RET(ARGS...); };
1487
1488 template<class RET, class FUNCTOR, class ...ARGS>
1489 struct StripSignature<RET (FUNCTOR::*) (ARGS...) &>
1490 { using Sig = RET(ARGS...); };
1491
1492 template<class RET, class FUNCTOR, class ...ARGS>
1493 struct StripSignature<RET (FUNCTOR::*) (ARGS...) const &>
1494 { using Sig = RET(ARGS...); };
1495
1496 template<class RET, class FUNCTOR, class ...ARGS>
1497 struct StripSignature<RET (FUNCTOR::*) (ARGS...) & noexcept>
1498 { using Sig = RET(ARGS...); };
1499
1500 template<class RET, class FUNCTOR, class ...ARGS>
1501 struct StripSignature<RET (FUNCTOR::*) (ARGS...) const & noexcept>
1502 { using Sig = RET(ARGS...); };
1503};
1504
1505/// Deduce the template parameter `PROTOTYPE` from the signature of the
1506/// `operator()` of the functor supplied to the constructor of `function`.
1507template <
1508 class FP,
1509 class PROTOTYPE = typename
1510 FunctionDeductionHelper::StripSignature<decltype(&FP::operator())>::Sig
1511 >
1512function(FP) -> function<PROTOTYPE>;
1513
1514/// Deduce the template parameter `PROTOTYPE` from the signature of the
1515/// `operator()` of the functor supplied to the constructor of `function`.
1516template <
1517 class ALLOC,
1518 class FP,
1519 class PROTOTYPE = typename
1520 FunctionDeductionHelper::StripSignature<decltype(&FP::operator())>::Sig
1521 >
1522function(allocator_arg_t, ALLOC, FP) -> function<PROTOTYPE>;
1523#endif
1524
1525// FREE FUNCTIONS
1526template <class PROTOTYPE>
1528
1529/// Return true if the `function` argument is empty, otherwise return false.
1530template <class PROTOTYPE>
1532
1533template <class PROTOTYPE>
1535
1536/// Return false if the `function` argument is empty, otherwise return true.
1537template <class PROTOTYPE>
1539
1540/// Exchange the targets held by the specified `a` and specified `b`
1541/// objects. The behavior is undefined unless 'a.get_allocator() ==
1542/// b.get_allocator()'.
1543template <class PROTOTYPE>
1545
1546} // close namespace bsl
1547
1548// ============================================================================
1549// TEMPLATE AND INLINE FUNCTION DEFINITIONS
1550// ============================================================================
1551
1552
1553
1554#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1555
1556 // --------------------------------
1557 // class template Function_Variadic
1558 // --------------------------------
1559
1560// CREATORS
1561template <class RET, class... ARGS>
1562inline
1564Function_Variadic(const allocator_type& allocator)
1565 : d_rep(allocator)
1566{
1567}
1568
1569// MANIPULATORS
1570template <class RET, class... ARGS>
1571inline
1572RET bslstl::Function_Variadic<RET(ARGS...)>::operator()(ARGS... args) const
1573{
1574 // BDE_VERIFY pragma: push
1575 // BDE_VERIFY pragma: -SAL01 // Possible strict-aliasing violation
1576 Invoker *invoker_p = reinterpret_cast<Invoker*>(d_rep.invoker());
1577 // BDE_VERIFY pragma: pop
1578
1579#ifdef BDE_BUILD_TARGET_EXC
1580 if (! invoker_p) {
1581 throw bsl::bad_function_call();
1582 }
1583#else
1584 // Non-exception build
1585 BSLS_ASSERT_OPT(invoker_p);
1586#endif
1587
1588 // It is not necessary to call 'std::forward<ARGS>' because 'args...' is
1589 // not composed of forwarding references. The arguments to 'invoker_p',
1590 // however, are not the same as 'args...' but compatible types produced by
1591 // 'bslmf::ForwardingTypes' for efficiency.
1592 return invoker_p(&d_rep, args...);
1593}
1594
1595#endif
1596
1597namespace bslstl {
1598
1599#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
1600
1601 // -------------------------------------------------
1602 // struct template Function_IsInvocableWithPrototype
1603 // -------------------------------------------------
1604
1605#ifdef BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE
1606
1607/// This component-private `struct` template provides a boolean metafunction
1608/// that derives from `bsl::true_type` if a `bsl::function` object having a
1609/// prototype of `RET(ARGS...)` is constructible from an object of type
1610/// `FUNC`, and derives from `bsl::false_type` otherwise. This metafunction
1611/// is a wrapper around `bsl::invoke_result` that unwraps `FUNC` if it is a
1612/// specialization of `bslalg::NothrowMovableWrapper`; and, if
1613/// `bsl::invoke_result` provides a nested `type` typedef for `FUNC` and
1614/// `RET` is non-void, checks that the return type of the invoke operation
1615/// on `FUNC` is convertible to `RET`.
1616template <class RET, class FUNC, class... ARGS>
1617struct Function_IsInvocableWithPrototype<RET(ARGS...), FUNC>
1618: Function_InvokerUtil::IsFuncInvocable<RET(ARGS...), FUNC> {
1619};
1620
1621#else // if !defined(BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE)
1622
1623/// This component-private `struct` template provides a partial
1624/// specialization of `Function_IsInvocableWithPrototype` for any `FUNC`
1625/// type, and for `PROTOTYPE` types that are function types. This
1626/// specialization only exists in pre-C++11 (e.g. C++03) compilers. It
1627/// approximates a boolean metafunction for detecting whether the specified
1628/// `FUNC` type is Lvalue-Callable with the prototype `RET(ARGS...)`. This
1629/// approximation is extremely coarse, and only checks that the `FUNC` is
1630/// not an integral type. It does this for the sole purpose of ensuring
1631/// that there are no overload resolution ambiguities in the constructors
1632/// and assignment operators of `bsl::function`, which provide overloads for
1633/// both integral types (to accept the literal `0` is a null pointer
1634/// constant), and for callable types like `FUNC`.
1635template <class RET, class FUNC, class... ARGS>
1636struct Function_IsInvocableWithPrototype<RET(ARGS...), FUNC>
1637: bsl::integral_constant<bool, !bsl::is_integral<FUNC>::value> {
1638};
1639
1640#endif // !defined(BSLSTL_FUNCTION_INVOKERUTIL_SUPPORT_IS_FUNC_INVOCABLE)
1641#endif
1642
1643} // close package namespace
1644
1645
1646 // ----------------------------
1647 // class template bsl::function
1648 // ----------------------------
1649
1650// PRIVATE MANIPULATORS
1651template <class PROTOTYPE>
1652template <class FUNC>
1653inline
1656{
1657 typedef BloombergLP::bslstl::Function_InvokerUtil InvokerUtil;
1658 typedef InvokerUtil::GenericInvoker GenericInvoker;
1659 typedef typename Decay<FUNC>::type DecayedFunc;
1660
1661 const DecayedFunc& decayedFunc = func; // Force function-to-pointer decay.
1662 GenericInvoker *const invoker =
1663 InvokerUtil::invokerForFunc<PROTOTYPE>(decayedFunc);
1664
1665 this->d_rep.installFunc(BSLS_COMPILERFEATURES_FORWARD(FUNC, func),
1666 invoker);
1667}
1668
1669// CREATORS
1670template <class PROTOTYPE>
1675
1676template <class PROTOTYPE>
1681
1682template <class PROTOTYPE>
1683inline
1687 : Base(allocator)
1688{
1689}
1690
1691template <class PROTOTYPE>
1692inline
1696 : Base(allocator)
1697{
1698}
1699
1700template <class PROTOTYPE>
1702 : Base(allocator_type())
1703{
1704 this->d_rep.copyInit(original.d_rep);
1705}
1706
1707template <class PROTOTYPE>
1710 const function& original)
1711 : Base(allocator)
1712{
1713 this->d_rep.copyInit(original.d_rep);
1714}
1715
1716template <class PROTOTYPE>
1717inline
1719 BloombergLP::bslmf::MovableRef<function> original) BSLS_KEYWORD_NOEXCEPT
1720 : Base(MovableRefUtil::access(original).get_allocator())
1721{
1722 this->d_rep.moveInit(&MovableRefUtil::access(original).d_rep);
1723}
1724
1725template <class PROTOTYPE>
1727 allocator_arg_t,
1729 BloombergLP::bslmf::MovableRef<function> original)
1730 : Base(allocator)
1731{
1732 this->d_rep.moveInit(&MovableRefUtil::access(original).d_rep);
1733}
1734
1735// MANIPULATORS
1736template <class PROTOTYPE>
1739{
1740 function temp(allocator_arg, this->get_allocator(), rhs);
1741 this->d_rep.makeEmpty(); // Won't throw
1742 this->d_rep.moveInit(&temp.d_rep); // Won't throw
1743 return *this;
1744}
1745
1746template <class PROTOTYPE>
1749 BloombergLP::bslmf::MovableRef<function> rhs)
1750{
1751 function temp(allocator_arg, this->get_allocator(),
1752 MovableRefUtil::move(rhs));
1753 this->d_rep.makeEmpty(); // Won't throw
1754 this->d_rep.moveInit(&temp.d_rep); // Won't throw
1755 return *this;
1756}
1757
1758template <class PROTOTYPE>
1761{
1762 this->d_rep.makeEmpty();
1763 return *this;
1764}
1765
1766template <class PROTOTYPE>
1767inline
1769{
1770 this->d_rep.swap(other.d_rep); // Won't throw
1771}
1772
1773template <class PROTOTYPE>
1774template<class TP>
1775inline
1777{
1778 return this->d_rep.template target<TP>();
1779}
1780
1781// ACCESSORS
1782
1783#ifdef BSLS_COMPILERFEATURES_SUPPORT_OPERATOR_EXPLICIT
1784template <class PROTOTYPE>
1785inline
1787{
1788 // If there is an invoker, then this function is non-empty (return true);
1789 // otherwise it is empty (return false).
1790 return 0 != this->d_rep.invoker();
1791}
1792#endif // BSLS_COMPILERFEATURES_SUPPORT_OPERATOR_EXPLICIT
1793
1794template <class PROTOTYPE>
1795inline
1801
1802template <class PROTOTYPE>
1803template<class TP>
1804inline
1806{
1807#if defined(BSLS_PLATFORM_CMP_MSVC) && BSLS_PLATFORM_CMP_VERSION < 1900
1808 // MSVC 2013 has a problem with implicit conversion to 'const nullptr_t*'.
1809 return (const TP*) this->d_rep.target<TP>();
1810#else
1811 return this->d_rep.template target<TP>();
1812#endif
1813}
1814
1815template <class PROTOTYPE>
1816const std::type_info&
1818{
1819 return this->d_rep.target_type();
1820}
1821
1822#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1823// CONVERSIONS TO LEGACY TYPE
1824template <class PROTOTYPE>
1825inline
1826bsl::function<PROTOTYPE>::operator BloombergLP::bdef_Function<PROTOTYPE *>&()
1828{
1829 typedef BloombergLP::bdef_Function<PROTOTYPE *> Ret;
1830 return *static_cast<Ret*>(this);
1831}
1832
1833template <class PROTOTYPE>
1834inline
1836operator const BloombergLP::bdef_Function<PROTOTYPE *>&() const
1838{
1839 typedef const BloombergLP::bdef_Function<PROTOTYPE *> Ret;
1840 return *static_cast<Ret*>(this);
1841}
1842
1843template <class PROTOTYPE>
1844inline
1845BloombergLP::bslma::Allocator *
1847{
1848 return get_allocator().mechanism();
1849}
1850
1851template <class PROTOTYPE>
1852inline
1854{
1855 return this->d_rep.isInplace();
1856}
1857#endif // BDE_OMIT_INTERNAL_DEPRECATED
1858
1859// FREE FUNCTIONS
1860template <class PROTOTYPE>
1861inline
1864{
1865 return !f;
1866}
1867
1868template <class PROTOTYPE>
1869inline
1870bool bsl::operator==(bsl::nullptr_t,
1872{
1873 return !f;
1874}
1875
1876template <class PROTOTYPE>
1877inline
1880{
1881 return !!f;
1882}
1883
1884template <class PROTOTYPE>
1885inline
1888{
1889 return !!f;
1890}
1891
1892template <class PROTOTYPE>
1893inline
1896{
1897 a.swap(b);
1898}
1899
1900 // --------------------------------------------------------------
1901 // specialization of class template Function_InvokerUtil_Dispatch
1902 // --------------------------------------------------------------
1903
1904
1905namespace bslstl {
1906
1907/// Specialization of null checker for instantiations of `bsl::function`.
1908/// This specialization treats an empty `bsl::function` as a null object.
1909template <class PROTO>
1910struct Function_InvokerUtilNullCheck<bsl::function<PROTO> > {
1911
1912 // CLASS METHODS
1913
1914 /// Return true if the `bsl::function` specified by `f` is empty; else
1915 /// false.
1916 static bool isNull(const bsl::function<PROTO>& f)
1917 {
1918 return !f;
1919 }
1920};
1921
1922} // close package namespace
1923
1924
1925// Undo 'BSLS_ASSERT' filename fix -- See @ref bsls_assertimputil
1926#ifdef BSLS_ASSERTIMPUTIL_AVOID_STRING_CONSTANTS
1927#undef BSLS_ASSERTIMPUTIL_FILE
1928#define BSLS_ASSERTIMPUTIL_FILE BSLS_ASSERTIMPUTIL_DEFAULTFILE
1929#endif
1930
1931#endif // End C++11 code
1932
1933#endif // End C++11 code
1934
1935// ----------------------------------------------------------------------------
1936// Copyright 2020 Bloomberg Finance L.P.
1937//
1938// Licensed under the Apache License, Version 2.0 (the "License");
1939// you may not use this file except in compliance with the License.
1940// You may obtain a copy of the License at
1941//
1942// http://www.apache.org/licenses/LICENSE-2.0
1943//
1944// Unless required by applicable law or agreed to in writing, software
1945// distributed under the License is distributed on an "AS IS" BASIS,
1946// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1947// See the License for the specific language governing permissions and
1948// limitations under the License.
1949// ----------------------------- END-OF-FILE ----------------------------------
1950
1951/** @} */
1952/** @} */
1953/** @} */
Definition bslstl_function.h:731
Forward declaration.
Definition bslstl_function.h:934
function(const BloombergLP::bslmf::MovableRef< FUNC > &func, typename enable_if< ! IsReferenceCompatible< typename Decay< FUNC >::type, function >::value &&IsInvocableWithPrototype< typename Decay< FUNC >::type >::value, int >::type=0)
Definition bslstl_function.h:1134
function(allocator_arg_t, const allocator_type &allocator, BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func, typename enable_if< ! IsReferenceCompatible< typename Decay< FUNC >::type, function >::value &&IsInvocableWithPrototype< typename Decay< FUNC >::type >::value, int >::type=0)
Definition bslstl_function.h:1169
BSLMF_NESTED_TRAIT_DECLARATION(function, bsl::is_nothrow_move_constructible)
BSLMF_NESTED_TRAIT_DECLARATION(function, BloombergLP::bslma::UsesBslmaAllocator)
BSLMF_NESTED_TRAIT_DECLARATION(function, BloombergLP::bslmf::UsesAllocatorArgT)
enable_if< IsInvocableWithPrototype< typenameDecay< FUNC >::type >::value, function & >::type operator=(bsl::reference_wrapper< FUNC > rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function.h:1344
Function_Rep::allocator_type allocator_type
Definition bslstl_function.h:1007
enable_if<!IsReferenceCompatible< typenameDecay< FUNC >::type, function >::value &&IsInvocableWithPrototype< typenameDecay< FUNC >::type >::value, function & >::type operator=(BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) rhs)
Definition bslstl_function.h:1299
Imp::Type Type
Definition bslmf_forwardingtype.h:439
Definition bslstl_function_rep.h:132
RET result_type
Definition bslstl_function.h:850
Function_Rep d_rep
Definition bslstl_function.h:835
Function_Rep::allocator_type allocator_type
Definition bslstl_function.h:851
Definition bslstl_function.h:802
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:1856
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2012
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2018
#define BSLS_DEPRECATE_FEATURE(UOR, FEATURE, MESSAGE)
Definition bsls_deprecatefeature.h:319
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:609
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
BloombergLP::bslma::Allocator * allocator() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function.h:1846
function & operator=(const function &rhs)
Definition bslstl_function.h:1738
function & operator=(BloombergLP::bslmf::MovableRef< function > rhs)
Definition bslstl_function.h:1748
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function.h:1797
const std::type_info & target_type() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function.h:1817
bool isInplace() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function.h:1853
function(allocator_arg_t, const allocator_type &allocator, const function &original)
Definition bslstl_function.h:1708
function(allocator_arg_t, const allocator_type &allocator, BloombergLP::bslmf::MovableRef< function > original)
Definition bslstl_function.h:1726
function & operator=(nullptr_t) BSLS_KEYWORD_NOEXCEPT
Set this object to empty and return *this.
Definition bslstl_function.h:1760
void swap(function &other) BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function.h:1768
TP * target() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function.h:1776
function() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function.h:1671
function(const function &original)
Definition bslstl_function.h:1701
function(BloombergLP::bslmf::MovableRef< function > original) BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function.h:1718
Definition bdlb_printmethods.h:283
BloombergLP::bsls::Nullptr_Impl::Type nullptr_t
Definition bsls_nullptr.h:281
void swap(array< VALUE_TYPE, SIZE > &lhs, array< VALUE_TYPE, SIZE > &rhs)
bool operator==(const memory_resource &a, const memory_resource &b)
bool operator!=(const memory_resource &a, const memory_resource &b)
Definition bslstl_algorithm.h:82
Definition bdldfp_decimal.h:5188
Definition bslmf_enableif.h:525
Definition bslmf_integralconstant.h:244
Definition bslmf_isfunction.h:232
Definition bslmf_isnothrowmoveconstructible.h:358
BSLS_DEPRECATE_FEATURE("bsl", "deprecated_cpp17_standard_library_features", "do not use") typedef ARG1 first_argument_type
BSLS_DEPRECATE_FEATURE("bsl", "deprecated_cpp17_standard_library_features", "do not use") typedef ARG argument_type
Definition bslstl_function.h:755
static bool isNull(const bsl::function< PROTO > &f)
Definition bslstl_function.h:1916
Definition bslstl_function_invokerutil.h:294
Definition bslstl_function.h:894