BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmf_istransparentpredicate.h
Go to the documentation of this file.
1/// @file bslmf_istransparentpredicate.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmf_istransparentpredicate.h -*-C++-*-
8#ifndef INCLUDED_BSLMF_ISTRANSPARENTPREDICATE
9#define INCLUDED_BSLMF_ISTRANSPARENTPREDICATE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmf_istransparentpredicate bslmf_istransparentpredicate
15/// @brief Support detection of whether a predicate functor is transparent.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmf
19/// @{
20/// @addtogroup bslmf_istransparentpredicate
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmf_istransparentpredicate-purpose"> Purpose</a>
25/// * <a href="#bslmf_istransparentpredicate-classes"> Classes </a>
26/// * <a href="#bslmf_istransparentpredicate-description"> Description </a>
27/// * <a href="#bslmf_istransparentpredicate-usage"> Usage </a>
28/// * <a href="#bslmf_istransparentpredicate-example-1-specifying-behavior-of-comparator"> Example 1: Specifying Behavior Of Comparator </a>
29///
30/// # Purpose {#bslmf_istransparentpredicate-purpose}
31/// Support detection of whether a predicate functor is transparent.
32///
33/// # Classes {#bslmf_istransparentpredicate-classes}
34///
35/// - bslmf::IsTransparentPredicate: Detects `is_transparent`
36///
37/// @see bslstl_map, bslstl_set
38///
39/// # Description {#bslmf_istransparentpredicate-description}
40/// This component provides a metafunction,
41/// `bslmf::IsTransparentPredicate`, that can be used to detect whether a
42/// comparator is transparent (supports heterogeneous comparisons). If the
43/// comparator has a nested type named `is_transparent`, the template inherits
44/// from `true_type`, otherwise it inherits from `false_type`.
45///
46/// ## Usage {#bslmf_istransparentpredicate-usage}
47///
48///
49/// This section illustrates intended use of this component.
50///
51/// ### Example 1: Specifying Behavior Of Comparator {#bslmf_istransparentpredicate-example-1-specifying-behavior-of-comparator}
52///
53///
54/// In this example, we demonstrate the use of `IsTransparentPredicate` to
55/// determine different comparator's behavior. Our goal is to create an
56/// overload of an associative container's method that participates in overload
57/// resolution only if the comparator is transparent, otherwise we fall back on
58/// a default behavior.
59///
60/// First, we define simple container, `Vector`, that is used as a foundation
61/// for our associative container:
62/// @code
63/// template <class TYPE>
64/// class Vector {
65/// // DATA
66/// const TYPE * d_begin_p; // pointer to the beginning
67/// const TYPE * d_end_p; // pointer to the end
68///
69/// public:
70/// // CREATORS
71/// Vector(const TYPE *first, const TYPE *last)
72/// // Construct an object that references the specified 'first' and
73/// // 'last' items in the sequence.
74/// : d_begin_p(first)
75/// , d_end_p(last)
76/// {
77/// }
78///
79/// // ACCESSORS
80/// const TYPE *begin() const
81/// // Return a reference providing non-modifiable access to the first
82/// // object in the underlying sequence.
83/// {
84/// return d_begin_p;
85/// }
86///
87/// const TYPE *end() const
88/// // Return a reference providing non-modifiable access to the last
89/// // object in the underlying sequence.
90/// {
91/// return d_end_p;
92/// }
93/// };
94/// @endcode
95/// Then we define simple type, `String`, that is used as a key. Note that we
96/// have comparison operators that allow to compare both two `String` objects
97/// and `String` object with character sequence.
98/// @code
99/// class String {
100/// // CLASS DATA
101/// static int s_numObjectsCreated; // total number of created instances
102///
103/// // DATA
104/// const char *d_data_p; // reference to a string
105///
106/// public:
107/// // CLASS METHODS
108/// static int numObjectsCreated()
109/// // Return the total number of created instances of class 'String'.
110/// {
111/// return s_numObjectsCreated;
112/// }
113///
114/// // CREATORS
115/// String()
116/// // Construct an empty string
117/// : d_data_p("")
118/// {
119/// ++s_numObjectsCreated;
120/// }
121///
122/// String(const char *data) // IMPLICIT
123/// // Construct a string that references the specified 'data'. The
124/// // behavior is undefined unless 'data' points to a null-terminated
125/// // string.
126/// : d_data_p(data)
127/// {
128/// ++s_numObjectsCreated;
129/// }
130///
131/// // FREE FUNCTIONS
132/// friend bool operator<(const String& lhs, const String& rhs)
133/// // Return 'true' if the value of the specified 'lhs' string is
134/// // lexicographically less than that of the specified 'rhs' string,
135/// // and 'false' otherwise.
136/// {
137/// const char *lhsData = lhs.d_data_p;
138/// const char *rhsData = rhs.d_data_p;
139/// while (true) {
140/// if (*lhsData < *rhsData) {
141/// return true; // RETURN
142/// }
143/// else if (*lhsData > *rhsData || *lhsData == '\0') {
144/// return false; // RETURN
145/// }
146/// ++lhsData;
147/// ++rhsData;
148/// }
149/// }
150///
151/// friend bool operator<(const String& lhs, const char *rhs)
152/// // Return 'true' if the value of the specified 'lhs' string is
153/// // lexicographically less than the specified 'rhs' character
154/// // sequence, and 'false' otherwise.
155/// {
156/// const char *lhsData = lhs.d_data_p;
157/// while (true) {
158/// if (*lhsData < *rhs) {
159/// return true; // RETURN
160/// }
161/// else if (*lhsData > *rhs || *lhsData == '\0') {
162/// return false; // RETURN
163/// }
164/// ++lhsData;
165/// ++rhs;
166/// }
167/// }
168///
169/// friend bool operator<(const char *lhs, const String& rhs)
170/// // Return 'true' if the specified 'lhs' character sequence is
171/// // lexicographically less than the value of the specified 'rhs'
172/// // string, and 'false' otherwise.
173/// {
174/// const char *rhsData = rhs.d_data_p;
175/// while (true) {
176/// if (*lhs < *rhsData) {
177/// return true; // RETURN
178/// }
179/// else if (*lhs > *rhsData || *lhs == '\0') {
180/// return false; // RETURN
181/// }
182/// ++lhs;
183/// ++rhsData;
184/// }
185/// }
186/// };
187///
188/// int String::s_numObjectsCreated = 0;
189/// @endcode
190/// Next we define our associative container. Note that we use
191/// `IsTransparentPredicate` for a method with `enable_if` in the return type.
192/// This adds our function template into the function overload resolution set if
193/// and only if the comparison function object is considered transparent, using
194/// a technique known as "SFINAE".
195/// @code
196/// template <class t_COMPARATOR>
197/// class FlatStringSet {
198///
199/// // DATA
200/// t_COMPARATOR d_comparator; // comparison object
201/// Vector<String> d_data; // stores the data
202///
203/// public:
204/// // TYPES
205/// typedef const String * const_iterator;
206///
207/// // CREATORS
208/// template <class INPUT_ITERATOR>
209/// FlatStringSet(INPUT_ITERATOR first,
210/// INPUT_ITERATOR last,
211/// const t_COMPARATOR& comparator = t_COMPARATOR());
212/// // Create a set, and insert each 'String' object in the sequence
213/// // starting at the specified 'first' element, and ending
214/// // immediately before the specified 'last' element, ignoring those
215/// // keys having a value equivalent to that which appears earlier in
216/// // the sequence. Optionally specify a 'comparator' used to order
217/// // keys contained in this object. If 'comparator' is not supplied,
218/// // a default-constructed object of the (template parameter) type
219/// // 't_COMPARATOR' is used. This operation has 'O[N]' complexity,
220/// // where 'N' is the number of elements between 'first' and 'last'.
221/// // The (template parameter) type 'INPUT_ITERATOR' shall meet the
222/// // requirements of an input iterator defined in the C++11 standard
223/// // [24.2.3] providing access to values of a type convertible to
224/// // 'String', and 'String' must be 'emplace-constructible' from '*i'
225/// // into this set, where 'i' is a dereferenceable iterator in the
226/// // range '[first .. last)'. The behavior is undefined unless
227/// // 'first' and 'last' refer to a sequence of valid values where
228/// // 'first' is at a position at or before 'last', the range is
229/// // ordered according to 't_COMPARATOR', and there are no duplicates
230/// // in the range.
231///
232/// // ACCESSORS
233/// const_iterator begin() const;
234/// // Return an iterator providing non-modifiable access to the first
235/// // 'String' object in the ordered sequence of 'String' objects
236/// // maintained by this set, or the 'end' iterator if this set is
237/// // empty.
238///
239/// const_iterator end() const;
240/// // Return an iterator providing non-modifiable access to the
241/// // past-the-end element in the ordered sequence of 'String' objects
242/// // maintained by this set.
243///
244/// const_iterator find(const String& key) const
245/// // Return an iterator to the element that compares equal to the
246/// // specified 'key' if such an element exists, and an end iterator
247/// // otherwise.
248/// //
249/// // Note: implemented inline due to Sun CC compilation error.
250/// {
251/// for (const_iterator first = begin(); first != end(); ++first) {
252/// if (d_comparator(key, *first)) {
253/// return end(); // RETURN
254/// }
255/// if (!d_comparator(*first, key)) {
256/// return first; // RETURN
257/// }
258/// }
259/// return end();
260/// }
261///
262/// template <class t_KEY>
263/// typename bsl::enable_if<IsTransparentPredicate<t_COMPARATOR,
264/// t_KEY>::value,
265/// const_iterator>::type
266/// find(const t_KEY& key) const
267/// // Return an iterator to the element that compares equal to the
268/// // specified 'key' if such an element exists, and an end iterator
269/// // otherwise.
270/// //
271/// // Note: implemented inline due to Sun CC compilation error.
272/// {
273/// for (const_iterator first = begin(); first != end(); ++first) {
274/// if (d_comparator(key, *first)) {
275/// return end(); // RETURN
276/// }
277/// if (!d_comparator(*first, key)) {
278/// return first; // RETURN
279/// }
280/// }
281/// return end();
282/// }
283///
284/// int size() const;
285/// // Return the number of elements in this container.
286/// };
287///
288/// // CREATORS
289/// template <class t_COMPARATOR>
290/// template <class INPUT_ITERATOR>
291/// FlatStringSet<t_COMPARATOR>::FlatStringSet(INPUT_ITERATOR first,
292/// INPUT_ITERATOR last,
293/// const t_COMPARATOR& comparator)
294/// : d_comparator(comparator),
295/// d_data(first, last)
296/// {
297/// }
298///
299/// // ACCESSORS
300/// template <class t_COMPARATOR>
301/// typename FlatStringSet<t_COMPARATOR>::const_iterator
302/// FlatStringSet<t_COMPARATOR>::begin() const
303/// {
304/// return d_data.begin();
305/// }
306///
307/// template <class t_COMPARATOR>
308/// typename FlatStringSet<t_COMPARATOR>::const_iterator
309/// FlatStringSet<t_COMPARATOR>::end() const
310/// {
311/// return d_data.end();
312/// }
313///
314/// template <class t_COMPARATOR>
315/// int FlatStringSet<t_COMPARATOR>::size() const
316/// {
317/// return static_cast<int>(end() - begin());
318/// }
319/// @endcode
320/// Then we define two comparators. These classes are completely identical
321/// except that one defines an `is_transparent` type, and the other does not.
322/// @code
323/// struct TransparentComp
324/// // This class can be used as a comparator for containers. It has a
325/// // nested type 'is_transparent', so it is classified as transparent by
326/// // the 'bslmf::IsTransparentPredicate' metafunction and can be used for
327/// // heterogeneous comparison.
328/// {
329/// // TYPES
330/// typedef void is_transparent;
331///
332/// // ACCESSORS
333/// template <class LHS, class RHS>
334/// bool operator()(const LHS& lhs, const RHS& rhs) const
335/// // Return 'true' if the specified 'lhs' is less than the specified
336/// // 'rhs' and 'false' otherwise.
337/// {
338/// return lhs < rhs;
339/// }
340/// };
341///
342/// struct NonTransparentComp
343/// // This class can be used as a comparator for containers. It has no
344/// // nested type 'is_transparent', so it is classified as
345/// // non-transparent by the 'bslmf::IsTransparentPredicate' metafunction
346/// // and can not be used for heterogeneous comparison.
347/// {
348/// template <class LHS, class RHS>
349/// bool operator()(const LHS& lhs, const RHS& rhs) const
350/// // Return 'true' if the specified 'lhs' is less than the specified
351/// // 'rhs' and 'false' otherwise.
352/// {
353/// return lhs < rhs;
354/// }
355/// };
356/// @endcode
357/// Next we create an array of `String` objects and two `FlatStringSet` objects,
358/// basing on this array and having different comparators, transparent and
359/// non-transparent. Note that creation of `FlatStringSet` object does not
360/// increase number of created `String` objects, because it just holds pointers
361/// to these objects, but does not copy them.
362/// @code
363/// int OBJECTS_NUMBER = String::numObjectsCreated();
364/// assert(0 == OBJECTS_NUMBER);
365///
366/// String data[] = { "1", "2", "3", "5" };
367/// enum { dataSize = sizeof data / sizeof *data };
368///
369/// assert(OBJECTS_NUMBER + 4 == String::numObjectsCreated());
370/// OBJECTS_NUMBER = String::numObjectsCreated();
371///
372/// FlatStringSet<NonTransparentComp> nts(data, data + dataSize);
373/// FlatStringSet< TransparentComp> ts(data, data + dataSize);
374///
375/// assert(4 == nts.size() );
376/// assert(4 == ts.size() );
377/// assert(OBJECTS_NUMBER == String::numObjectsCreated());
378/// @endcode
379/// Then we call `find` method of set, having non-transparent comparator.
380/// Explicit creation of temporary `String` object predictably increases the
381/// number of created `String` objects. But using character sequence as a
382/// parameter for `find` method increases it too. Because comparison operator
383/// that accepts two `String` objects is used instead of operator that accepts
384/// `String` and char sequence, so `String` constructor is called implicitly.
385/// @code
386/// assert(nts.begin() + 0 == nts.find(String("1")) );
387/// assert(nts.begin() + 1 == nts.find(String("2")) );
388/// assert(nts.begin() + 2 == nts.find(String("3")) );
389/// assert(nts.begin() + 3 == nts.find(String("5")) );
390/// assert(nts.end() == nts.find(String("6")) );
391///
392/// assert(OBJECTS_NUMBER + 5 == String::numObjectsCreated());
393/// OBJECTS_NUMBER = String::numObjectsCreated();
394///
395/// assert(nts.begin() + 0 == nts.find( "1" ) );
396/// assert(nts.begin() + 1 == nts.find( "2" ) );
397/// assert(nts.begin() + 2 == nts.find( "3" ) );
398/// assert(nts.begin() + 3 == nts.find( "5" ) );
399/// assert(nts.end() == nts.find( "6" ) );
400///
401/// assert(OBJECTS_NUMBER + 5 == String::numObjectsCreated());
402/// OBJECTS_NUMBER = String::numObjectsCreated();
403/// @endcode
404/// Finally we call `find` method of set, having transparent comparator.
405/// Explicit creation of temporary `String` object still increases the number of
406/// created `String` objects. But using character sequence as a parameter for
407/// `find` method does not. Because comparison operator that accepts `String`
408/// and char sequence is available and more appropriate then operator accepting
409/// two `String` objects. So there is no need for implicit constructor
410/// invocation.
411/// @code
412/// assert( ts.begin() + 0 == ts.find(String("1")) );
413/// assert( ts.begin() + 1 == ts.find(String("2")) );
414/// assert( ts.begin() + 2 == ts.find(String("3")) );
415/// assert( ts.begin() + 3 == ts.find(String("5")) );
416/// assert( ts.end() == ts.find(String("6")) );
417///
418/// assert(OBJECTS_NUMBER + 5 == String::numObjectsCreated());
419/// OBJECTS_NUMBER = String::numObjectsCreated();
420///
421/// assert( ts.begin() + 0 == ts.find( "1" ) );
422/// assert( ts.begin() + 1 == ts.find( "2" ) );
423/// assert( ts.begin() + 2 == ts.find( "3" ) );
424/// assert( ts.begin() + 3 == ts.find( "5" ) );
425/// assert( ts.end() == ts.find( "6" ) );
426///
427/// assert(OBJECTS_NUMBER == String::numObjectsCreated());
428/// @endcode
429/// @}
430/** @} */
431/** @} */
432
433/** @addtogroup bsl
434 * @{
435 */
436/** @addtogroup bslmf
437 * @{
438 */
439/** @addtogroup bslmf_istransparentpredicate
440 * @{
441 */
442
443#include <bslmf_integralconstant.h>
444#include <bslmf_voidtype.h>
445
446
447namespace bslmf {
448
449/// This `struct` template implements a meta-function to determine whether
450/// the (template parameter) `t_COMPARATOR` is transparent (has a publicly
451/// accessible member that is a type named `is_transparent`). This generic
452/// default template derives from `bsl::false_type`. Template
453/// specializations are provided (below) that derive from `bsl::true_type`.
454template <class t_COMPARATOR, class t_KEY, class = void>
457
458/// This specialization of `IsTransparentPredicate`, for when the (template
459/// parameter) `t_COMPARATOR` is transparent, derives from `bsl::true_type`.
460template <class t_COMPARATOR, class t_KEY>
462 t_COMPARATOR,
463 t_KEY,
464 BSLMF_VOIDTYPE(typename t_COMPARATOR::is_transparent)> : bsl::true_type {
465};
466
467} // close package namespace
468
469
470#endif
471
472// ----------------------------------------------------------------------------
473// Copyright 2019 Bloomberg Finance L.P.
474//
475// Licensed under the Apache License, Version 2.0 (the "License");
476// you may not use this file except in compliance with the License.
477// You may obtain a copy of the License at
478//
479// http://www.apache.org/licenses/LICENSE-2.0
480//
481// Unless required by applicable law or agreed to in writing, software
482// distributed under the License is distributed on an "AS IS" BASIS,
483// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
484// See the License for the specific language governing permissions and
485// limitations under the License.
486// ----------------------------- END-OF-FILE ----------------------------------
487
488/** @} */
489/** @} */
490/** @} */
#define BSLMF_VOIDTYPE(ARG)
Definition bslmf_voidtype.h:335
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlbb_blob.h:576
Definition bslmf_integralconstant.h:244
Definition bslmf_istransparentpredicate.h:455