BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlf_overloaded.h
Go to the documentation of this file.
1/// @file bdlf_overloaded.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlf_overloaded.h -*-C++-*-
8#ifndef INCLUDED_BDLF_OVERLOADED
9#define INCLUDED_BDLF_OVERLOADED
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlf_overloaded bdlf_overloaded
15/// @brief Provide a type for constructing overload sets.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlf
19/// @{
20/// @addtogroup bdlf_overloaded
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlf_overloaded-purpose"> Purpose</a>
25/// * <a href="#bdlf_overloaded-classes"> Classes </a>
26/// * <a href="#bdlf_overloaded-description"> Description </a>
27/// * <a href="#bdlf_overloaded-usage"> Usage </a>
28/// * <a href="#bdlf_overloaded-example-1-basic-usage"> Example 1: Basic Usage </a>
29///
30/// # Purpose {#bdlf_overloaded-purpose}
31/// Provide a type for constructing overload sets.
32///
33/// # Classes {#bdlf_overloaded-classes}
34///
35/// - bdlf::Overloaded: template for overload sets
36///
37/// @see bslstl_variant, bdljsn_json
38///
39/// # Description {#bdlf_overloaded-description}
40/// This component provides a template class, `bdlf::Overloaded`,
41/// that allows you to construct callable objects that contain several function
42/// call overloads.
43///
44/// This is especially useful when dealing with variant objects, as they can be
45/// passed to `std::visit` or to `bsl::visit`, and depending on the type stored
46/// in the variant, the correct element of the overload set will be called.
47///
48/// This component requires C++17.
49///
50/// ## Usage {#bdlf_overloaded-usage}
51///
52///
53/// This section illustrates intended use of this component.
54///
55/// ### Example 1: Basic Usage {#bdlf_overloaded-example-1-basic-usage}
56///
57///
58/// First, create a bsl::variant object that can contain several different
59/// types.
60/// @code
61/// bsl::variant<unsigned, double, bsl::string> v;
62/// @endcode
63/// Next, Create an Overload object containing several options:
64/// @code
65/// bdlf::Overloaded over{
66/// [] (unsigned) {return 1;}
67/// , [] (double) {return 2;}
68/// , [] (const bsl::string&) {return 3;}
69/// };
70/// @endcode
71/// Set the value of variant, and then call std::visit, passing the overload set
72/// and the variant. Check the return value to see that the right lambda was
73/// called.
74/// @code
75/// v = 2U;
76/// assert(1 == bsl::visit(over, v));
77/// v = 2.0;
78/// assert(2 == bsl::visit(over, v));
79/// v = bsl::string("2.0");
80/// assert(3 == bsl::visit(over, v));
81/// @endcode
82/// @}
83/** @} */
84/** @} */
85
86/** @addtogroup bdl
87 * @{
88 */
89/** @addtogroup bdlf
90 * @{
91 */
92/** @addtogroup bdlf_overloaded
93 * @{
94 */
95
96#include <bslscm_version.h>
97
99#include <bsls_keyword.h>
100
101#include <utility> // std::forward
102
103
104namespace bdlf {
105
106#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
107
108 // ================================
109 // class Overloaded_FunctionPointer
110 // ================================
111
112/// Overloaded_FunctionPointer wraps a function pointer. It is implicitly
113/// constructible from the pointer, and provides an `operator()` method that
114/// calls through to the underlying function.
115template <class RET, class ...ARGS>
116struct Overloaded_FunctionPointer
117{
118 // TYPES
119 using FpType = RET (*)(ARGS...);
120
121 // PUBLIC DATA
122 FpType d_fp;
123
124 // CREATORS
125
126 /// Construct this object from the specified `f`.
127 Overloaded_FunctionPointer(FpType f); // IMPLICIT
128
129 // ACCESSORS
130
131 /// Call the function passed to the constructor with the specified `args`.
132 RET operator()(ARGS&&... args) const;
133};
134
135 // ========================================
136 // class Overloaded_NoexceptFunctionPointer
137 // ========================================
138
139/// Overloaded_NoexceptFunctionPointer wraps a function pointer. It is
140/// implicitly constructible from the pointer, and provides an `operator()`
141/// method that calls through to the underlying function.
142template <class RET, class ...ARGS>
143struct Overloaded_NoexceptFunctionPointer
144{
145
146 // TYPES
147 using FpType = RET (*)(ARGS...) noexcept;
148
149 // PUBLIC DATA
150 FpType d_fp;
151
152 // CREATORS
153
154 /// Construct this object from the specified `f`.
155 Overloaded_NoexceptFunctionPointer(FpType f); // IMPLICIT
156
157 // ACCESSORS
158
159 /// Call the function passed to the constructor with the specified `args`.
160 RET operator()(ARGS&&... args) const noexcept;
161};
162
163 // ======================================
164 // class Overloaded_MemberFunctionPointer
165 // ======================================
166
167/// The class Overloaded_MemberFunctionPointer wraps a member function
168/// pointer. It is implicitly constructible from the pointer, and provides
169/// an `operator()` that takes an object of the appropriate type and other
170/// arguments, and forwards them on to the underlying function.
171template <class OBJ, class RET, class ...ARGS>
172struct Overloaded_MemberFunctionPointer
173{
174 // TYPES
175 using FpType = RET (OBJ::*)(ARGS...);
176
177 // PUBLIC DATA
178 FpType d_fp;
179
180 // CREATORS
181
182 /// Construct this object from the specified `f`.
183 Overloaded_MemberFunctionPointer(FpType f); // IMPLICIT
184
185 // ACCESSORS
186
187 /// Call the member function passed to the constructor using the specified
188 /// `obj` with the specified `args`, and return the result of the call.
189 RET operator()(OBJ * obj, ARGS&&... args) const;
190};
191
192 // ===========================================
193 // class Overloaded_ConstMemberFunctionPointer
194 // ===========================================
195
196/// The class Overloaded_ConstMemberFunctionPointer wraps a member function
197/// pointer. It is implicitly constructible from the pointer, and provides
198/// an `operator()` that takes an object of the appropriate type and other
199/// arguments, and forwards them on to the underlying function.
200template <class OBJ, class RET, class ...ARGS>
201struct Overloaded_ConstMemberFunctionPointer
202{
203 // TYPES
204 using FpType = RET (OBJ::*)(ARGS...) const;
205
206 // PUBLIC DATA
207 FpType d_fp;
208
209 // CREATORS
210
211 /// Construct this object from the specified `f`.
212 Overloaded_ConstMemberFunctionPointer(FpType f); // IMPLICIT
213
214 // ACCESSORS
215
216 /// Call the member function passed to the constructor using the specified
217 /// `obj` with the specified `args`, and return the result of the call.
218 RET operator()(const OBJ * obj, ARGS&&... args) const;
219};
220
221 // ==============================================
222 // class Overloaded_NoexceptMemberFunctionPointer
223 // ==============================================
224
225/// The class Overloaded_NoexceptMemberFunctionPointer wraps a member function
226/// pointer. It is implicitly constructible from the pointer, and provides an
227/// `operator()` that takes an object of the appropriate type and other
228/// arguments, and forwards them on to the underlying function.
229template <class OBJ, class RET, class ...ARGS>
230struct Overloaded_NoexceptMemberFunctionPointer
231{
232 // TYPES
233 using FpType = RET (OBJ::*)(ARGS...) noexcept;
234
235 // PUBLIC DATA
236 FpType d_fp;
237
238 // CREATORS
239
240 /// Construct this object from the specified `f`.
241 Overloaded_NoexceptMemberFunctionPointer(FpType f); // IMPLICIT
242
243 // ACCESSORS
244
245 /// Call the member function passed to the constructor using the specified
246 /// `obj` with the specified `args`, and return the result of the call.
247 RET operator()(OBJ * obj, ARGS&&... args) const noexcept;
248};
249
250 // ===================================================
251 // class Overloaded_ConstNoexceptMemberFunctionPointer
252 // ===================================================
253
254/// The class Overloaded_ConstNoexceptMemberFunctionPointer wraps a member
255/// function pointer. It is implicitly constructible from the pointer, and
256/// provides an `operator()` that takes an object of the appropriate type
257/// and other arguments, and forwards them on to the underlying function.
258template <class OBJ, class RET, class ...ARGS>
259struct Overloaded_ConstNoexceptMemberFunctionPointer
260{
261 // TYPES
262 using FpType = RET (OBJ::*)(ARGS...) const noexcept;
263
264 // PUBLIC DATA
265 FpType d_fp;
266
267 // CREATORS
268
269 /// Construct this object from the specified `f`.
270 Overloaded_ConstNoexceptMemberFunctionPointer(FpType f); // IMPLICIT
271
272 // ACCESSORS
273
274 /// Call the member function passed to the constructor using the specified
275 /// `obj` with the specified `args`, and return the result of the call.
276 RET operator()(const OBJ * obj, ARGS&&... args) const noexcept;
277
278};
279
280// Implementation Notes
281// --------------------
282// Given a callable, figure out what the appropriate wrapper is. For class
283// types, (lambdas, say) there is no wrapper; the class can be used directly.
284// For function pointers, we use Overloaded_FunctionPointer or
285// Overloaded_NoexceptFunctionPointer. For member functions, we have four
286// varieties.
287
288 // ========================
289 // class Overloaded_Wrapper
290 // ========================
291
292template <class TYPE>
293struct Overloaded_Wrapper {
294 // TYPES
295 using Type = TYPE;
296};
297
298// -- Wrappers for function pointers
299template <class RET, class ...ARGS>
300struct Overloaded_Wrapper<RET (*)(ARGS...)> {
301 // TYPES
302 using Type = Overloaded_FunctionPointer<RET, ARGS...>;
303};
304
305template <class RET, class ...ARGS>
306struct Overloaded_Wrapper<RET (*)(ARGS...) noexcept> {
307 // TYPES
308 using Type = Overloaded_NoexceptFunctionPointer<RET, ARGS...>;
309};
310
311// -- Wrappers for member function pointers
312template <class OBJ, class RET, class ...ARGS>
313struct Overloaded_Wrapper<RET (OBJ::*)(ARGS...)> {
314 // TYPES
315 using Type = Overloaded_MemberFunctionPointer<OBJ, RET, ARGS...>;
316};
317
318template <class OBJ, class RET, class ...ARGS>
319struct Overloaded_Wrapper<RET (OBJ::*)(ARGS...) const> {
320 // TYPES
321 using Type = Overloaded_ConstMemberFunctionPointer<OBJ, RET, ARGS...>;
322};
323
324template <class OBJ, class RET, class ...ARGS>
325struct Overloaded_Wrapper<RET (OBJ::*)(ARGS...) noexcept> {
326 // TYPES
327 using Type = Overloaded_NoexceptMemberFunctionPointer<OBJ, RET, ARGS...>;
328};
329
330template <class OBJ, class RET, class ...ARGS>
331struct Overloaded_Wrapper<RET (OBJ::*)(ARGS...) const noexcept> {
332 // TYPES
333 using Type =
334 Overloaded_ConstNoexceptMemberFunctionPointer<OBJ, RET, ARGS...>;
335};
336
337 // ================
338 // class Overloaded
339 // ================
340
341// `Overloaded` is a structure that holds a series of objects that have
342// an `operator()`, and provides the ability to call one of them determined
343// by the parameters that are passed to the operator.
344template<class... TS>
345struct Overloaded : Overloaded_Wrapper<TS>::Type...
346{
347 using Overloaded_Wrapper<TS>::Type::operator()...;
348};
349
350// CLASS TEMPLATE DEDUCTION GUIDES
351template<class... TS>
352Overloaded(TS...) -> Overloaded<TS...>;
353
354// ============================================================================
355// TEMPLATE AND INLINE FUNCTION DEFINITIONS
356// ============================================================================
357
358 // --------------------------------
359 // class Overloaded_FunctionPointer
360 // --------------------------------
361
362// ACCESSORS
363template <class RET, class ...ARGS>
364Overloaded_FunctionPointer<RET, ARGS...>::Overloaded_FunctionPointer(
365 typename Overloaded_FunctionPointer<RET, ARGS...>::FpType f)
366: d_fp(f)
367{
368}
369
370template <class RET, class ...ARGS>
371inline
372RET Overloaded_FunctionPointer<RET, ARGS...>::operator()(ARGS&&... args) const
373{
374 return d_fp(std::forward<ARGS>(args)...);
375}
376
377 // ----------------------------------------
378 // class Overloaded_NoexceptFunctionPointer
379 // ----------------------------------------
380
381// ACCESSORS
382template <class RET, class ...ARGS>
383Overloaded_NoexceptFunctionPointer<RET, ARGS...>
384 ::Overloaded_NoexceptFunctionPointer(
385 typename Overloaded_NoexceptFunctionPointer<RET, ARGS...>::FpType f)
386: d_fp(f)
387{
388}
389
390template <class RET, class ...ARGS>
391inline
392RET Overloaded_NoexceptFunctionPointer<RET, ARGS...>::operator()
393 (ARGS&&... args) const noexcept
394{
395 return d_fp(std::forward<ARGS>(args)...);
396}
397
398 // --------------------------------------
399 // class Overloaded_MemberFunctionPointer
400 // --------------------------------------
401
402// ACCESSORS
403template <class OBJ, class RET, class ...ARGS>
404Overloaded_MemberFunctionPointer<OBJ, RET, ARGS...>
405 ::Overloaded_MemberFunctionPointer(
406 typename Overloaded_MemberFunctionPointer<OBJ, RET, ARGS...>::FpType f)
407: d_fp(f)
408{
409}
410
411template <class OBJ, class RET, class ...ARGS>
412inline
413RET Overloaded_MemberFunctionPointer<OBJ, RET, ARGS...>::operator()
414 (OBJ * obj, ARGS&&... args) const
415{
416 return (obj->*d_fp)(std::forward<ARGS>(args)...);
417}
418
419 // -------------------------------------------
420 // class Overloaded_ConstMemberFunctionPointer
421 // -------------------------------------------
422
423// ACCESSORS
424template <class OBJ, class RET, class ...ARGS>
425Overloaded_ConstMemberFunctionPointer<OBJ, RET, ARGS...>
426 ::Overloaded_ConstMemberFunctionPointer(typename
427 Overloaded_ConstMemberFunctionPointer<OBJ, RET, ARGS...>::FpType f)
428: d_fp(f)
429{
430}
431
432template <class OBJ, class RET, class ...ARGS>
433inline
434RET Overloaded_ConstMemberFunctionPointer<OBJ, RET, ARGS...>::operator()
435 (const OBJ * obj, ARGS&&... args) const
436{
437 return (obj->*d_fp)(std::forward<ARGS>(args)...);
438}
439
440 // ----------------------------------------------
441 // class Overloaded_NoexceptMemberFunctionPointer
442 // ----------------------------------------------
443
444// ACCESSORS
445template <class OBJ, class RET, class ...ARGS>
446Overloaded_NoexceptMemberFunctionPointer<OBJ, RET, ARGS...>
447 ::Overloaded_NoexceptMemberFunctionPointer(typename
448 Overloaded_NoexceptMemberFunctionPointer<OBJ, RET, ARGS...>::FpType f)
449: d_fp(f)
450{
451}
452
453template <class OBJ, class RET, class ...ARGS>
454inline
455RET Overloaded_NoexceptMemberFunctionPointer<OBJ, RET, ARGS...>
456 ::operator()(OBJ * obj, ARGS&&... args) const noexcept
457{
458 return (obj->*d_fp)(std::forward<ARGS>(args)...);
459}
460
461 // ---------------------------------------------------
462 // class Overloaded_ConstNoexceptMemberFunctionPointer
463 // ---------------------------------------------------
464
465// ACCESSORS
466template <class OBJ, class RET, class ...ARGS>
467Overloaded_ConstNoexceptMemberFunctionPointer<OBJ, RET, ARGS...>
468 ::Overloaded_ConstNoexceptMemberFunctionPointer(typename
469 Overloaded_ConstNoexceptMemberFunctionPointer<OBJ, RET, ARGS...>::FpType f)
470: d_fp(f)
471{
472}
473
474template <class OBJ, class RET, class ...ARGS>
475inline
476RET Overloaded_ConstNoexceptMemberFunctionPointer<OBJ, RET, ARGS...>
477 ::operator()(const OBJ * obj, ARGS&&... args) const noexcept
478{
479 return (obj->*d_fp)(std::forward<ARGS>(args)...);
480}
481
482#endif
483
484} // close package namespace
485
486
487#endif // ! defined(INCLUDED_BDLF_OVERLOADED)
488
489// ----------------------------------------------------------------------------
490// Copyright 2024 Bloomberg Finance L.P.
491//
492// Licensed under the Apache License, Version 2.0 (the "License");
493// you may not use this file except in compliance with the License.
494// You may obtain a copy of the License at
495//
496// http://www.apache.org/licenses/LICENSE-2.0
497//
498// Unless required by applicable law or agreed to in writing, software
499// distributed under the License is distributed on an "AS IS" BASIS,
500// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
501// See the License for the specific language governing permissions and
502// limitations under the License.
503// ----------------------------- END-OF-FILE ----------------------------------
504
505/** @} */
506/** @} */
507/** @} */
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlf_bind.h:979