BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bsltf_copymovestate.h
Go to the documentation of this file.
1/// @file bsltf_copymovestate.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsltf_copymovestate.h -*-C++-*-
8#ifndef INCLUDED_BSLTF_COPYMOVESTATE
9#define INCLUDED_BSLTF_COPYMOVESTATE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsltf_copymovestate bsltf_copymovestate
15/// @brief Provide an enumeration of copy/move state, including unsupported.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsltf
19/// @{
20/// @addtogroup bsltf_copymovestate
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsltf_copymovestate-purpose"> Purpose</a>
25/// * <a href="#bsltf_copymovestate-classes"> Classes </a>
26/// * <a href="#bsltf_copymovestate-description"> Description </a>
27/// * <a href="#bsltf_copymovestate-enumerators"> Enumerators </a>
28/// * <a href="#bsltf_copymovestate-usage"> Usage </a>
29/// * <a href="#bsltf_copymovestate-example-1-tracking-an-object-s-history"> Example 1: Tracking an object's history </a>
30///
31/// # Purpose {#bsltf_copymovestate-purpose}
32/// Provide an enumeration of copy/move state, including unsupported.
33///
34/// # Classes {#bsltf_copymovestate-classes}
35///
36/// - bsltf::CopyMoveState: namespace for copy/move state enumeration
37///
38/// @see bsltf_copymovetracker
39///
40/// # Description {#bsltf_copymovestate-description}
41/// This component provides a `struct`, `bsltf::CopyMoveState`,
42/// which serves as a namespace for enumerating the copy and move state of an
43/// object, including an unknown value indicating that the test type does not
44/// support tracking this information. A test type can, using a single instance
45/// of this `enum` track whether the object was most recently copied into, moved
46/// into, or moved from.
47///
48/// In instances where more than one operatation needs to be tracked (i.e., the
49/// object was copied into, then moved from), the logical-OR of multiple
50/// enumerators can be stored in a single variable, but doing so does not
51/// preserve the order of the operations nor whether any operation occured more
52/// than once; if such information is needed, multiple instances of this `enum`
53/// can be used.
54///
55/// The `CopyMoveState` namespace also provides a `toAscii` method that
56/// converts an enumerator into its name represented as a null-terminated ASCII
57/// string.
58///
59/// ## Enumerators {#bsltf_copymovestate-enumerators}
60///
61///
62/// @code
63/// Name Description
64/// ---------------------- ---------------------------------------------------
65/// e_ORIGINAL Original value; object was not copied or moved into
66/// e_COPIED_INTO Object was copied into
67/// e_COPIED_CONST_INTO Object was copied into from a const reference
68/// e_COPIED_NONCONST_INTO Object was copied into from a non-const reference
69/// e_MOVED_INTO Object was moved into (from a movable reference)
70/// e_MOVED_FROM Object was moved from
71/// e_UNKNOWN Object does not track copy/move history
72/// @endcode
73///
74/// All of the enumerators have unique values. The `e_ORIGINAL` enumerator has
75/// value 0 (no bits set). The values for `e_COPIED_CONST_INTO` and
76/// `e_COPIED_NONCONST_INTO` each have the `e_COPIED_INTO` bit set as well as
77/// one other bit. The remaining enumerators have one bit set each, sharing no
78/// bits with any of the other enumerators.
79///
80/// When converted to `bool`, `e_ORIGINAL` yields `false` whereas the rest yield
81/// `true`. When `e_UNKNOWN` is not used, this conversion makes it easy create
82/// a binary test of whether an object was copied or moved.
83///
84/// ## Usage {#bsltf_copymovestate-usage}
85///
86///
87/// This section illustrates intended use of this component.
88///
89/// ### Example 1: Tracking an object's history {#bsltf_copymovestate-example-1-tracking-an-object-s-history}
90///
91///
92/// In this example, we show how `CopyMoveState` can be used to track the most
93/// recent copy or move operation applied to an object.
94///
95/// First, we define a `TrackedValue` type that contains an integer value and a
96/// `CopyMoveState`
97/// @code
98/// #include <bsltf_copymovestate.h>
99/// #include <bslmf_movableref.h>
100/// #include <cstring>
101///
102/// struct TrackedValue {
103/// int d_value;
104/// bsltf::CopyMoveState::Enum d_copyMoveState;
105/// @endcode
106/// Next, we define a value constructor that indicates that the object was
107/// neither copied into, moved into, nor moved from:
108/// @code
109/// TrackedValue(int v = 0) // IMPLICIT
110/// : d_value(v)
111/// , d_copyMoveState(bsltf::CopyMoveState::e_ORIGINAL) { }
112/// @endcode
113/// Next, we define a copy constructor that records the fact that the object was
114/// copied into. As in the case of most copy constructors, the original is
115/// accessed through a `const` reference, and the copy/moved state reflects that
116/// fact.
117/// @code
118/// TrackedValue(const TrackedValue& original)
119/// : d_value(original.d_value)
120/// , d_copyMoveState(bsltf::CopyMoveState::e_COPIED_CONST_INTO) { }
121/// @endcode
122/// Next, we define a move constructor that records both that the object being
123/// constructed was moved into, but also that the original object was moved
124/// from.
125/// @code
126/// TrackedValue(bslmf::MovableRef<TrackedValue> original)
127/// : d_value(bslmf::MovableRefUtil::access(original).d_value)
128/// , d_copyMoveState(bsltf::CopyMoveState::e_MOVED_INTO)
129/// {
130/// TrackedValue& originalRef = original;
131/// originalRef.d_value = -1;
132/// originalRef.d_copyMoveState = bsltf::CopyMoveState::e_MOVED_FROM;
133/// }
134/// @endcode
135/// Next, we declare the destructor and assignment operators, but, for the
136/// purpose of this example, we don't need to see their implementations:
137/// @code
138/// //! ~TrackedValue() = default;
139///
140/// TrackedValue& operator=(const TrackedValue&);
141/// TrackedValue& operator=(bslmf::MovableRef<TrackedValue>);
142/// @endcode
143/// Then, we define accessors for the value and copy/move state.
144/// @code
145/// int value() const { return d_value; }
146/// bsltf::CopyMoveState::Enum copyMoveState() const
147/// { return d_copyMoveState; }
148/// @endcode
149/// Now, outside of the class definition or (better yet) as a hidden friend
150/// function, we define an ADL customization point used to retrieve the
151/// copy/move state of the tracked value. This free function will be called in
152/// generic code that doesn't know whether the type it's working with has a
153/// `copyMoveState` accessor; a default is provided for types that don't:
154/// @code
155/// friend bsltf::CopyMoveState::Enum copyMoveState(const TrackedValue& v)
156/// {
157/// return v.copyMoveState();
158/// }
159/// };
160/// @endcode
161/// Finally, we test our `TrackedValue` class by creating an object, copying it,
162/// and moving it. After each step, we test that each object's copy/move state
163/// is as expected. Note that `e_COPIED_INTO` names a bit that is set in both
164/// of the other `e_COPIED_*` enumerators. At the end, we verify that the
165/// copy/move state is correctly converted to a string by the `toAscii` method
166/// and that the copy/move state of a plain `int` is always "e_UNKNOWN".
167/// @code
168/// int main()
169/// {
170/// typedef bsltf::CopyMoveState Cms;
171///
172/// TrackedValue tv1(42);
173/// assert(42 == tv1.value());
174/// assert(Cms::e_ORIGINAL == tv1.copyMoveState());
175/// assert(Cms::get(tv1) == tv1.copyMoveState());
176///
177/// TrackedValue tv2(tv1); // Copy
178/// assert(42 == tv2.value());
179/// assert(Cms::e_COPIED_CONST_INTO == tv2.copyMoveState());
180/// assert(Cms::e_COPIED_INTO & tv2.copyMoveState());
181///
182/// TrackedValue tv3(bslmf::MovableRefUtil::move(tv1)); // Move
183/// assert(42 == tv3.value());
184/// assert(Cms::e_MOVED_INTO == tv3.copyMoveState());
185/// assert(-1 == tv1.value());
186/// assert(Cms::e_MOVED_FROM == tv1.copyMoveState());
187///
188/// assert(0 == std::strcmp("MOVED_FROM",
189/// Cms::toAscii(tv1.copyMoveState())));
190///
191/// assert(Cms::e_UNKNOWN == Cms::get(5)); // 'int' doesn't track state
192/// }
193/// @endcode
194/// @}
195/** @} */
196/** @} */
197
198/** @addtogroup bsl
199 * @{
200 */
201/** @addtogroup bsltf
202 * @{
203 */
204/** @addtogroup bsltf_copymovestate
205 * @{
206 */
207
208#include <bslscm_version.h>
209
210#include <bslmf_matchanytype.h>
211
212
213namespace bsltf {
214
215 //=====================
216 // struct CopyMoveState
217 //=====================
218
220 public:
221 // TYPES
222 enum Enum {
223 // Enumeration of copy state.
224
231 e_UNKNOWN = 0x20,
233 };
234
235 // CLASS METHODS
236
237 /// For the specified `obj` return `copyMoveState(obj)`.
238 ///
239 /// \note Note that `getCopyMoveState` is an ADL customization point; if not customized
240 /// for a specific `TYPE`, a default implementation returning
241 /// `e_UNKNOWN` is invoked.
242 template <class TYPE>
243 static Enum get(const TYPE& obj);
244
245 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
246 /// includes the `e_COPIED_CONST_INTO` bits but not `e_UNKNOWN`.
247 template <class TYPE>
248 static bool isCopiedConstInto(const TYPE& v);
249
250 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
251 /// includes the `e_COPIED_INTO` bit but not `e_UNKNOWN`; otherwise
252 /// return `false`.
253 template <class TYPE>
254 static bool isCopiedInto(const TYPE& v);
255
256 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
257 /// includes the `e_COPIED_NONCONST_INTO` bits but not `e_UNKNOWN`.
258 template <class TYPE>
259 static bool isCopiedNonconstInto(const TYPE& v);
260
261 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
262 /// includes the `e_MOVED_FROM` bit but not `e_UNKNOWN`; otherwise
263 /// return `false`.
264 template <class TYPE>
265 static bool isMovedFrom(const TYPE& v);
266
267 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
268 /// includes the `e_MOVED_INTO` bit but not `e_UNKNOWN`; otherwise
269 /// return `false`.
270 template <class TYPE>
271 static bool isMovedInto(const TYPE& v);
272
273 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
274 /// does not include any of the `e_COPIED_INTO`, `e_MOVED_INTO`, or `e_UNKNOWN` bits; otherwise return 'false.
275 ///
276 /// \note Note that this
277 /// function's return value is unaffected by the `e_MOVED_FROM` bit.
278 template <class TYPE>
279 static bool isOriginal(const TYPE& v);
280
281 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
282 /// includes the `e_UNKNOWN` bit; otherwise return 'false.
283 template <class TYPE>
284 static bool isUnknown(const TYPE& v);
285
286 /// Return `true` if the specified `val` is a valid value of `Enum`;
287 /// otherwise `false`. A valid value is any of the enumerators or the
288 /// bitwise OR of any of the enumerators except `e_UNKNOWN` with
289 /// `e_MOVED_FROM`.
290 static bool isValid(Enum val);
291
292 /// For the specified `obj_p` address and specified `state`, invoke `setCopyMoveState(obj_p, state)`.
293 ///
294 /// \note Note that `setCopyMoveState` is
295 /// an ADL customization point; if not customized for a specific `TYPE`,
296 /// a no-op default implementation is invoked.
297 template <class TYPE>
298 static void set(TYPE *obj_p, Enum state);
299
300 /// Return the non-modifiable string representation corresponding to the
301 /// specified enumeration `value`, if it exists, and a unique (error)
302 /// string otherwise. The string representation of `value` matches its
303 /// corresponding enumerator name with the "e_" prefix elided. For
304 /// example:
305 /// @code
306 /// bsl::cout << CopyMoveState::toAscii(CopyMoveState::e_COPIED_INTO);
307 /// @endcode
308 /// will print the following on standard output:
309 /// @code
310 /// COPIED_INTO
311 /// @endcode
312 /// Any of the *_INTO enums can be bitwise ORed with `e_MOVED_FROM`, in
313 /// which case the resulting string will be a comma-separated list of
314 /// two names, e.g., "COPIED_CONST_INTO, MOVED_FROM".
315 ///
316 /// \note Note that specifying a `value` that does not match any valid combination of
317 /// enumerators will result in a string representation that is distinct
318 /// from any of those corresponding to the enumerators, but is otherwise
319 /// unspecified.
320 static const char *toAscii(CopyMoveState::Enum value);
321};
322
323// FREE FUNCTIONS
324
325/// Return `true` if `value` is `e_ORIGINAL`; otherwise return `false`.
327
328/// Return `true` if the integral values of the specified `a` and `b`
329/// compare equal; otherwise return `false`.
330bool operator==(CopyMoveState::Enum a, int b);
331bool operator==(int a, CopyMoveState::Enum b);
332
333/// Return `true` if the integral values of the specified `a` and `b` do not
334/// compare equal; otherwise return `false`.
335bool operator!=(CopyMoveState::Enum a, int b);
336bool operator!=(int a, CopyMoveState::Enum b);
337
338/// Return `e_UNKWOWN`. Called from `CopyMoveState::get`, this default
339/// implementation is called if a customized `copyMoveState` is not found via ADL for a specific type.
340///
341/// \note Note that this overload is defined such
342/// that, if `copyMoveState` is customized for a type, the customization is
343/// "inherited" by derived types.
344inline
346
347/// Do nothing. Called from `CopyMoveState::set`, this default
348/// implementation is called if a customized `getCopyMoveState` is not found via ADL for a specific type.
349///
350/// \note Note that this overload is defined such
351/// that, if `setCopyMoveState` is customized for a type, the customization
352/// is "inherited" by derived types.
354
355/// Print the specified `value` as a string. This is an ADL customization
356/// point.
358
359// ============================================================================
360// INLINE AND TEMPLATE FUNCTION IMPLEMENTATIONS
361// ============================================================================
362
363 //---------------------
364 // struct CopyMoveState
365 //---------------------
366
367// CLASS METHODS
368template <class TYPE>
369inline
371{
372 return copyMoveState(obj);
373}
374
375template <class TYPE>
376inline bool CopyMoveState::isCopiedConstInto(const TYPE& v)
377{
379}
380
381template <class TYPE>
382inline bool CopyMoveState::isCopiedInto(const TYPE& v)
383{
384 return e_COPIED_INTO == (get(v) & (e_COPIED_INTO | e_UNKNOWN));
385}
386
387template <class TYPE>
388inline bool CopyMoveState::isCopiedNonconstInto(const TYPE& v)
389{
390 return e_COPIED_NONCONST_INTO == (get(v) &
392}
393
394template <class TYPE>
395inline bool CopyMoveState::isMovedFrom(const TYPE& v)
396{
397 return e_MOVED_FROM == (get(v) & (e_MOVED_FROM | e_UNKNOWN));
398}
399
400template <class TYPE>
401inline bool CopyMoveState::isMovedInto(const TYPE& v)
402{
403 return e_MOVED_INTO == (get(v) & (e_MOVED_INTO | e_UNKNOWN));
404}
405
406template <class TYPE>
407inline bool CopyMoveState::isOriginal(const TYPE& v)
408{
409 return 0 == (get(v) & (e_COPIED_INTO | e_MOVED_INTO | e_UNKNOWN));
410}
411
412template <class TYPE>
413inline bool CopyMoveState::isUnknown(const TYPE& v)
414{
415 return bool(get(v) & e_UNKNOWN);
416}
417
418template <class TYPE>
419inline void CopyMoveState::set(TYPE *obj_p, Enum state)
420{
421 setCopyMoveState(obj_p, state);
422}
423
425{
426 // 'VALID_MASK' is a bitset with a bit representing every enumerated value
427 // less than or equal to 'e_UNKNOWN', with a 1 bit representing a valid
428 // enumerator value.
429 static const unsigned long long
430 k_VALID_MASK = (1ULL << e_ORIGINAL |
431 1ULL << e_COPIED_INTO |
432 1ULL << e_COPIED_CONST_INTO |
433 1ULL << e_COPIED_NONCONST_INTO |
434 1ULL << e_MOVED_INTO |
435 1ULL << e_MOVED_FROM |
436
437 1ULL << (e_COPIED_INTO | e_MOVED_FROM) |
440 1ULL << (e_MOVED_INTO | e_MOVED_FROM) |
441
442 1ULL << e_UNKNOWN );
443
444 if (val > e_UNKNOWN) {
445 return false;
446 }
447 else {
448 return (1ULL << val) & k_VALID_MASK; // Find 'e' in bitset
449 }
450}
451
452} // close package namespace
453
454// FREE FUNCTIONS
456{
457 return value == 0;
458}
459
461{
462 return int(a) == b;
463}
464
466{
467 return a == int(b);
468}
469
471{
472 return int(a) != b;
473}
474
476{
477 return a != int(b);
478}
479
481{
482 return CopyMoveState::e_UNKNOWN;
483}
484
486{
487}
488
489
490
491#endif // INCLUDED_BSLTF_COPYMOVESTATE
492
493// ----------------------------------------------------------------------------
494// Copyright 2023 Bloomberg Finance L.P.
495//
496// Licensed under the Apache License, Version 2.0 (the "License");
497// you may not use this file except in compliance with the License.
498// You may obtain a copy of the License at
499//
500// http://www.apache.org/licenses/LICENSE-2.0
501//
502// Unless required by applicable law or agreed to in writing, software
503// distributed under the License is distributed on an "AS IS" BASIS,
504// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
505// See the License for the specific language governing permissions and
506// limitations under the License.
507// ----------------------------- END-OF-FILE ----------------------------------
508
509/** @} */
510/** @} */
511/** @} */
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bsltf_allocargumenttype.h:92
bool operator!=(const AllocBitwiseMoveableTestType &lhs, const AllocBitwiseMoveableTestType &rhs)
void setCopyMoveState(void *, CopyMoveState::Enum)
bool operator!(CopyMoveState::Enum value)
Return true if value is e_ORIGINAL; otherwise return false.
void debugprint(const ArgumentType< N > &object)
Definition bsltf_argumenttype.h:562
CopyMoveState::Enum copyMoveState(bslmf::MatchAnyType)
bool operator==(const AllocBitwiseMoveableTestType &lhs, const AllocBitwiseMoveableTestType &rhs)
Definition bslmf_matchanytype.h:152
Definition bsltf_copymovestate.h:219
Enum
Definition bsltf_copymovestate.h:222
@ e_COPIED_NONCONST_INTO
Definition bsltf_copymovestate.h:228
@ e_COPIED_INTO
Definition bsltf_copymovestate.h:226
@ e_MAX_ENUM
Definition bsltf_copymovestate.h:232
@ e_UNKNOWN
Definition bsltf_copymovestate.h:231
@ e_COPIED_CONST_INTO
Definition bsltf_copymovestate.h:227
@ e_MOVED_INTO
Definition bsltf_copymovestate.h:229
@ e_ORIGINAL
Definition bsltf_copymovestate.h:225
@ e_MOVED_FROM
Definition bsltf_copymovestate.h:230
static const char * toAscii(CopyMoveState::Enum value)
static void set(TYPE *obj_p, Enum state)
Definition bsltf_copymovestate.h:419
static bool isUnknown(const TYPE &v)
Definition bsltf_copymovestate.h:413
static Enum get(const TYPE &obj)
Definition bsltf_copymovestate.h:370
static bool isCopiedInto(const TYPE &v)
Definition bsltf_copymovestate.h:382
static bool isMovedInto(const TYPE &v)
Definition bsltf_copymovestate.h:401
static bool isValid(Enum val)
Definition bsltf_copymovestate.h:424
static bool isOriginal(const TYPE &v)
Definition bsltf_copymovestate.h:407
static bool isCopiedNonconstInto(const TYPE &v)
Definition bsltf_copymovestate.h:388
static bool isCopiedConstInto(const TYPE &v)
Definition bsltf_copymovestate.h:376
static bool isMovedFrom(const TYPE &v)
Definition bsltf_copymovestate.h:395