BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlb_pairutil.h
Go to the documentation of this file.
1/// @file bdlb_pairutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlb_pairutil.h -*-C++-*-
8#ifndef INCLUDED_BDLB_PAIRUTIL
9#define INCLUDED_BDLB_PAIRUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id$ $CSID$")
13
14/// @defgroup bdlb_pairutil bdlb_pairutil
15/// @brief Provide support functions for `bsl::pair`.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlb
19/// @{
20/// @addtogroup bdlb_pairutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlb_pairutil-purpose"> Purpose</a>
25/// * <a href="#bdlb_pairutil-classes"> Classes </a>
26/// * <a href="#bdlb_pairutil-description"> Description </a>
27/// * <a href="#bdlb_pairutil-usage"> Usage </a>
28/// * <a href="#bdlb_pairutil-example-1-basic-usage-of-tie-function"> Example 1: Basic Usage of tie Function </a>
29/// * <a href="#bdlb_pairutil-example-2-adapting-bsl-container-for-ranges"> Example 2: Adapting bsl Container For Ranges </a>
30///
31/// # Purpose {#bdlb_pairutil-purpose}
32/// Provide support functions for `bsl::pair`.
33///
34/// # Classes {#bdlb_pairutil-classes}
35///
36/// - bdlb::PairUtil: namespace for functions working with `bsl::pair`
37///
38/// # Description {#bdlb_pairutil-description}
39/// This component provides the class `bdlb::PairUtil`, which has
40/// the following tools for working with `bsl::pair`:
41/// * `tie`: function that is intended to be used in place of
42/// `bsl::tie` when the right-hand side of the
43/// assignment is a `bsl::pair`
44/// * `adaptForRanges`: function that adapt `bsl` containers whose value type
45/// is a `bsl::pair` type to work with range adaptors
46/// * `stdPairRefAdaptor`: function object that takes a `bsl::pair` by reference
47/// and returns a `std::pair` where each element is a
48/// reference to the corresponding member of the
49/// `bsl::pair`
50///
51/// ## Usage {#bdlb_pairutil-usage}
52///
53///
54/// This section illustrates intended use of this component.
55///
56/// ### Example 1: Basic Usage of tie Function {#bdlb_pairutil-example-1-basic-usage-of-tie-function}
57///
58///
59/// Suppose we need to implement a function that takes a `bsl::map` and stores
60/// into out-parameters the key and value corresponding to the first entry in
61/// the map. Using `bsl::map`s container interface, we can obtain a reference
62/// to a `bsl::pair` of the key and value. We can then use
63/// `bdlb::PairUtil::tie` to assign from both the key and value in a single
64/// expression:
65/// @code
66/// /// Load into the specified `key` and the specified `value` the key and
67/// /// value for the first entry in the specified `map` and return `true`,
68/// /// or else fail by storing 0 and an empty string and return `false`
69/// /// when `map` is empty.
70/// bool getFirst(int *key,
71/// bsl::string *value,
72/// const bsl::map<int, bsl::string>& map)
73/// {
74/// if (map.empty()) {
75/// *key = 0;
76/// value->clear();
77/// return false; // RETURN
78/// }
79/// bdlb::PairUtil::tie(*key, *value) = *map.begin();
80/// return true;
81/// }
82///
83/// void usageExample()
84/// {
85/// bsl::map<int, bsl::string> map;
86/// map[30782530] = "bbi10";
87///
88/// int uuid;
89/// bsl::string username;
90///
91/// bool result = getFirst(&uuid, &username, map);
92/// assert(result);
93/// assert(30782530 == uuid);
94/// assert("bbi10" == username);
95/// }
96/// @endcode
97///
98/// ### Example 2: Adapting bsl Container For Ranges {#bdlb_pairutil-example-2-adapting-bsl-container-for-ranges}
99///
100///
101/// Let's assume that we have a `bsl::map` storing employee indexes and their
102/// names, and we want to get a list of employee names:
103/// @code
104/// bsl::map<int, bsl::string_view> employees{{1, "John Dow"},
105/// {2, "Jane Dow"},
106/// {3, "James Dow"}};
107/// @endcode
108/// However, if we were to try and access the names using `bsl::views::values`
109/// we would see a compilation error:
110///
111/// auto names = employees | bsl::views::values; // does not compile
112/// auto namesIt = names.begin();
113/// assert("John Dow" == *namesIt);
114///
115/// This fails to because `bsl::pair`, unlike the `std::pair`, does not model
116/// the `tuple-like` concept, which is a requirement of the
117/// `bsl::views::values`. This problem can be resolved using the
118/// `bdlb::PairUtil::adaptForRanges` function on the container:
119/// @code
120/// auto names = employees | bdlb::PairUtil::adaptForRanges
121/// | bsl::views::values;
122/// auto namesIt = names.begin();
123/// assert("John Dow" == *namesIt);
124/// @endcode
125/// And of course this function allows you to create chains of adaptors using a
126/// pipeline operator:
127/// @code
128/// const auto startsWithJa = [](bsl::string_view name) -> bool
129/// {
130/// return name.starts_with("Ja");
131/// };
132///
133/// auto jaNames = employees | bdlb::PairUtil::adaptForRanges
134/// | bsl::views::values
135/// | bsl::views::filter(startsWithJa);
136/// assert(bsl::ranges::equal(jaNames,
137/// bsl::vector<bsl::string_view>{"Jane Dow",
138/// "James Dow"}));
139/// @endcode
140/// @}
141/** @} */
142/** @} */
143
144/** @addtogroup bdl
145 * @{
146 */
147/** @addtogroup bdlb
148 * @{
149 */
150/** @addtogroup bdlb_pairutil
151 * @{
152 */
153
154#include <bdlscm_version.h>
155
156#include <bslmf_assert.h>
158
159#include <bsls_libraryfeatures.h>
160
161#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES
162#include <bsl_ranges.h>
163#endif
164
165#include <bsl_utility.h>
166
167
168
169namespace bdlb {
170
171#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES
172
173 // =================================
174 // struct PairUtil_StdPairRefAdaptor
175 // =================================
176
177/// This component-private struct is a function object converting `bsl::pair`
178/// object into its standard counterpart storing references to the attributes
179/// of the original object.
180///
181/// See @ref bdlb_pairutil
182struct PairUtil_StdPairRefAdaptor {
183 public:
184 // ACCESSORS
185
186 /// Return `std::pair` containing references to the fields of the specified
187 /// `pair`.
188 template <class t_FIRST, class t_SECOND>
189 constexpr std::pair<t_FIRST&, t_SECOND&> operator()(
190 bsl::pair<t_FIRST, t_SECOND>& pair) const;
191 template <class t_FIRST, class t_SECOND>
192 constexpr std::pair<const t_FIRST&, const t_SECOND&> operator()(
193 const bsl::pair<t_FIRST, t_SECOND>& pair) const;
194};
195
196 // =====================================
197 // struct PairUtil_AdaptForRangesClosure
198 // =====================================
199
200/// This component-private struct is a function object converting ranges
201/// containing `bsl::pair`s to a range of `std::pair`s.
202///
203/// See @ref bdlb_pairutil
204struct PairUtil_AdaptForRangesClosure {
205 // ACCESSORS
206
207 /// Given a range of `bsl::pairs`, translate it to a range of `std::pair`s,
208 /// where each element of the resulting `std::pair`s is a reference to
209 /// corresponding member of the corresponding element of the bsl range.
210 template <class t_RANGE_BSL_PAIR>
211 auto operator()(t_RANGE_BSL_PAIR&& bslRange) const
212 -> decltype(bsl::views::transform(
213 bsl::forward<t_RANGE_BSL_PAIR>(bslRange),
214 std::declval<const PairUtil_StdPairRefAdaptor&>()));
215};
216#endif
217
218 // ==============
219 // class PairUtil
220 // ==============
221
222/// This `struct` provides a namespace for the functions that make working with
223/// `bsl::pair`-like containers more convenient or adapting such containers to
224/// work with standard library utilities.
225///
226/// See @ref bdlb_pairutil
227struct PairUtil {
228
229#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES
230 // CLASS DATA
231
232 /// A function object that takes a `bsl::pair` by reference and returns a
233 /// `std::pair` where each element is a reference to the corresponding
234 /// member of the `bsl::pair`.
235 static constexpr PairUtil_StdPairRefAdaptor stdPairRefAdaptor{};
236
237 /// A function object which, when applied to a range of `bsl::pair`s,
238 /// transforms it into a range of `std::pair`s, where the members of the
239 /// resultant `std::pair`s are references to the corresponding members of
240 /// the corresponding `bsl::pair`s in the input range.
241 static constexpr PairUtil_AdaptForRangesClosure adaptForRanges{};
242#endif
243
244 // CLASS METHODS
245
246 /// Return a `bsl::pair` object holding a reference to the specified
247 /// `first` and a reference to the specified `second`, respectively.
248 template <class t_FIRST, class t_SECOND>
249 static bsl::pair<t_FIRST&, t_SECOND&> tie(t_FIRST& first,
250 t_SECOND& second);
251};
252
253// ============================================================================
254// INLINE DEFINITIONS
255// ============================================================================
256
257// FREE OPERATORS
258
259#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES
260
261/// Translate the range of `bsl::pair`s into a range of `std::pair`s, where
262/// each `pair` of the resulting range is a `pair` of references to the
263/// corresponding members of the corresponding `pair` in the input range.
264template <class t_RANGE_BSL_PAIR>
265auto operator|(t_RANGE_BSL_PAIR&& bslRange,
266 const PairUtil_AdaptForRangesClosure&)
267 -> decltype(PairUtil::adaptForRanges(
268 bsl::forward<t_RANGE_BSL_PAIR>(bslRange)));
269#endif
270
271// ============================================================================
272// TEMPLATE AND INLINE FUNCTION DEFINITIONS
273// ============================================================================
274
275 // ---------------------------------
276 // struct PairUtil_StdPairRefAdaptor
277 // ---------------------------------
278
279#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES
280// ACCESSORS
281template <class t_FIRST, class t_SECOND>
282inline
283constexpr std::pair<t_FIRST&, t_SECOND&>
284PairUtil_StdPairRefAdaptor::operator()(
286{
287 BSLMF_ASSERT(!bsl::is_rvalue_reference_v<t_FIRST>);
288 BSLMF_ASSERT(!bsl::is_rvalue_reference_v<t_SECOND>);
289
290 return {pair.first, pair.second};
291}
292
293template <class t_FIRST, class t_SECOND>
294inline
295constexpr std::pair<const t_FIRST&, const t_SECOND&>
296PairUtil_StdPairRefAdaptor::operator()(
297 const bsl::pair<t_FIRST, t_SECOND>& pair) const
298{
299 BSLMF_ASSERT(!bsl::is_rvalue_reference_v<t_FIRST>);
300 BSLMF_ASSERT(!bsl::is_rvalue_reference_v<t_SECOND>);
301
302 return {pair.first, pair.second};
303}
304#endif
305
306 // -------------------------------------
307 // struct PairUtil_AdaptForRangesClosure
308 // -------------------------------------
309
310#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES
311template <class t_RANGE_BSL_PAIR>
312inline auto
313PairUtil_AdaptForRangesClosure::operator()(t_RANGE_BSL_PAIR&& bslRange) const
314 -> decltype(bsl::views::transform(
315 bsl::forward<t_RANGE_BSL_PAIR>(bslRange),
316 std::declval<const PairUtil_StdPairRefAdaptor&>()))
317{
318 return bsl::forward<t_RANGE_BSL_PAIR>(bslRange)
319 | bsl::views::transform(PairUtil::stdPairRefAdaptor);
320}
321#endif
322
323 // ---------------
324 // struct PairUtil
325 // ---------------
326
327// CLASS METHODS
328template <class t_FIRST, class t_SECOND>
329inline
330bsl::pair<t_FIRST&, t_SECOND&> PairUtil::tie(t_FIRST& first, t_SECOND& second)
331{
332 return bsl::pair<t_FIRST&, t_SECOND&>(first, second);
333}
334
335// FREE OPERATORS
336
337#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES
338template <class t_RANGE_BSL_PAIR>
339auto operator|(t_RANGE_BSL_PAIR&& bslRange,
340 const PairUtil_AdaptForRangesClosure&)
341 -> decltype(PairUtil::adaptForRanges(
342 bsl::forward<t_RANGE_BSL_PAIR>(bslRange)))
343{
344 return PairUtil::adaptForRanges(bsl::forward<t_RANGE_BSL_PAIR>(bslRange));
345}
346#endif
347
348} // close package namespace
349
350
351#endif
352
353// ----------------------------------------------------------------------------
354// Copyright 2023 Bloomberg Finance L.P.
355//
356// Licensed under the Apache License, Version 2.0 (the "License");
357// you may not use this file except in compliance with the License.
358// You may obtain a copy of the License at
359//
360// http://www.apache.org/licenses/LICENSE-2.0
361//
362// Unless required by applicable law or agreed to in writing, software
363// distributed under the License is distributed on an "AS IS" BASIS,
364// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
365// See the License for the specific language governing permissions and
366// limitations under the License.
367// ----------------------------- END-OF-FILE ----------------------------------
368
369/** @} */
370/** @} */
371/** @} */
Definition bslstl_pair.h:1280
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlb_algorithmworkaroundutil.h:74
Definition bdlb_pairutil.h:227
static bsl::pair< t_FIRST &, t_SECOND & > tie(t_FIRST &first, t_SECOND &second)
Definition bdlb_pairutil.h:330
TYPE first
Definition bslstl_pair.h:587
TYPE second
Definition bslstl_pair.h:933