BDE 4.14.0 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)`. Note that
238 /// `getCopyMoveState` is an ADL customization point; if not customized
239 /// for a specific `TYPE`, a default implementation returning
240 /// `e_UNKNOWN` is invoked.
241 template <class TYPE>
242 static Enum get(const TYPE& obj);
243
244 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
245 /// includes the `e_COPIED_CONST_INTO` bits but not `e_UNKNOWN`.
246 template <class TYPE>
247 static bool isCopiedConstInto(const TYPE& v);
248
249 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
250 /// includes the `e_COPIED_INTO` bit but not `e_UNKNOWN`; otherwise
251 /// return `false`.
252 template <class TYPE>
253 static bool isCopiedInto(const TYPE& v);
254
255 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
256 /// includes the `e_COPIED_NONCONST_INTO` bits but not `e_UNKNOWN`.
257 template <class TYPE>
258 static bool isCopiedNonconstInto(const TYPE& v);
259
260 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
261 /// includes the `e_MOVED_FROM` bit but not `e_UNKNOWN`; otherwise
262 /// return `false`.
263 template <class TYPE>
264 static bool isMovedFrom(const TYPE& v);
265
266 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
267 /// includes the `e_MOVED_INTO` bit but not `e_UNKNOWN`; otherwise
268 /// return `false`.
269 template <class TYPE>
270 static bool isMovedInto(const TYPE& v);
271
272 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
273 /// does not include any of the `e_COPIED_INTO`, `e_MOVED_INTO`, or
274 /// `e_UNKNOWN` bits; otherwise return 'false. Note that this
275 /// function's return value is unaffected by the `e_MOVED_FROM` bit.
276 template <class TYPE>
277 static bool isOriginal(const TYPE& v);
278
279 /// Return `true` if, for the specified `v`, `CopyMoveState::get(v)`
280 /// includes the `e_UNKNOWN` bit; otherwise return 'false.
281 template <class TYPE>
282 static bool isUnknown(const TYPE& v);
283
284 /// Return `true` if the specified `val` is a valid value of `Enum`;
285 /// otherwise `false`. A valid value is any of the enumerators or the
286 /// bitwise OR of any of the enumerators except `e_UNKNOWN` with
287 /// `e_MOVED_FROM`.
288 static bool isValid(Enum val);
289
290 /// For the specified `obj_p` address and specified `state`, invoke
291 /// `setCopyMoveState(obj_p, state)`. Note that `setCopyMoveState` is
292 /// an ADL customization point; if not customized for a specific `TYPE`,
293 /// a no-op default implementation is invoked.
294 template <class TYPE>
295 static void set(TYPE *obj_p, Enum state);
296
297 /// Return the non-modifiable string representation corresponding to the
298 /// specified enumeration `value`, if it exists, and a unique (error)
299 /// string otherwise. The string representation of `value` matches its
300 /// corresponding enumerator name with the "e_" prefix elided. For
301 /// example:
302 /// @code
303 /// bsl::cout << CopyMoveState::toAscii(CopyMoveState::e_COPIED_INTO);
304 /// @endcode
305 /// will print the following on standard output:
306 /// @code
307 /// COPIED_INTO
308 /// @endcode
309 /// Any of the *_INTO enums can be bitwise ORed with `e_MOVED_FROM`, in
310 /// which case the resulting string will be a comma-separated list of
311 /// two names, e.g., "COPIED_CONST_INTO, MOVED_FROM". Note that
312 /// specifying a `value` that does not match any valid combination of
313 /// enumerators will result in a string representation that is distinct
314 /// from any of those corresponding to the enumerators, but is otherwise
315 /// unspecified.
316 static const char *toAscii(CopyMoveState::Enum value);
317};
318
319// FREE FUNCTIONS
320
321/// Return `true` if `value` is `e_ORIGINAL`; otherwise return `false`.
323
324/// Return `true` if the integral values of the specified `a` and `b`
325/// compare equal; otherwise return `false`.
326bool operator==(CopyMoveState::Enum a, int b);
327bool operator==(int a, CopyMoveState::Enum b);
328
329/// Return `true` if the integral values of the specified `a` and `b` do not
330/// compare equal; otherwise return `false`.
331bool operator!=(CopyMoveState::Enum a, int b);
332bool operator!=(int a, CopyMoveState::Enum b);
333
334/// Return `e_UNKWOWN`. Called from `CopyMoveState::get`, this default
335/// implementation is called if a customized `copyMoveState` is not found
336/// via ADL for a specific type. Note that this overload is defined such
337/// that, if `copyMoveState` is customized for a type, the customization is
338/// "inherited" by derived types.
339inline
341
342/// Do nothing. Called from `CopyMoveState::set`, this default
343/// implementation is called if a customized `getCopyMoveState` is not found
344/// via ADL for a specific type. Note that this overload is defined such
345/// that, if `setCopyMoveState` is customized for a type, the customization
346/// is "inherited" by derived types.
348
349/// Print the specified `value` as a string. This is an ADL customization
350/// point.
352
353// ============================================================================
354// INLINE AND TEMPLATE FUNCTION IMPLEMENTATIONS
355// ============================================================================
356
357 //---------------------
358 // struct CopyMoveState
359 //---------------------
360
361// CLASS METHODS
362template <class TYPE>
363inline
365{
366 return copyMoveState(obj);
367}
368
369template <class TYPE>
370inline bool CopyMoveState::isCopiedConstInto(const TYPE& v)
371{
373}
374
375template <class TYPE>
376inline bool CopyMoveState::isCopiedInto(const TYPE& v)
377{
378 return e_COPIED_INTO == (get(v) & (e_COPIED_INTO | e_UNKNOWN));
379}
380
381template <class TYPE>
382inline bool CopyMoveState::isCopiedNonconstInto(const TYPE& v)
383{
384 return e_COPIED_NONCONST_INTO == (get(v) &
386}
387
388template <class TYPE>
389inline bool CopyMoveState::isMovedFrom(const TYPE& v)
390{
391 return e_MOVED_FROM == (get(v) & (e_MOVED_FROM | e_UNKNOWN));
392}
393
394template <class TYPE>
395inline bool CopyMoveState::isMovedInto(const TYPE& v)
396{
397 return e_MOVED_INTO == (get(v) & (e_MOVED_INTO | e_UNKNOWN));
398}
399
400template <class TYPE>
401inline bool CopyMoveState::isOriginal(const TYPE& v)
402{
403 return 0 == (get(v) & (e_COPIED_INTO | e_MOVED_INTO | e_UNKNOWN));
404}
405
406template <class TYPE>
407inline bool CopyMoveState::isUnknown(const TYPE& v)
408{
409 return bool(get(v) & e_UNKNOWN);
410}
411
412template <class TYPE>
413inline void CopyMoveState::set(TYPE *obj_p, Enum state)
414{
415 setCopyMoveState(obj_p, state);
416}
417
419{
420 // 'VALID_MASK' is a bitset with a bit representing every enumerated value
421 // less than or equal to 'e_UNKNOWN', with a 1 bit representing a valid
422 // enumerator value.
423 static const unsigned long long
424 k_VALID_MASK = (1ULL << e_ORIGINAL |
425 1ULL << e_COPIED_INTO |
426 1ULL << e_COPIED_CONST_INTO |
427 1ULL << e_COPIED_NONCONST_INTO |
428 1ULL << e_MOVED_INTO |
429 1ULL << e_MOVED_FROM |
430
431 1ULL << (e_COPIED_INTO | e_MOVED_FROM) |
434 1ULL << (e_MOVED_INTO | e_MOVED_FROM) |
435
436 1ULL << e_UNKNOWN );
437
438 if (val > e_UNKNOWN) {
439 return false;
440 }
441 else {
442 return (1ULL << val) & k_VALID_MASK; // Find 'e' in bitset
443 }
444}
445
446} // close package namespace
447
448// FREE FUNCTIONS
450{
451 return value == 0;
452}
453
455{
456 return int(a) == b;
457}
458
460{
461 return a == int(b);
462}
463
465{
466 return int(a) != b;
467}
468
470{
471 return a != int(b);
472}
473
475{
476 return CopyMoveState::e_UNKNOWN;
477}
478
480{
481}
482
483
484
485#endif // INCLUDED_BSLTF_COPYMOVESTATE
486
487// ----------------------------------------------------------------------------
488// Copyright 2023 Bloomberg Finance L.P.
489//
490// Licensed under the Apache License, Version 2.0 (the "License");
491// you may not use this file except in compliance with the License.
492// You may obtain a copy of the License at
493//
494// http://www.apache.org/licenses/LICENSE-2.0
495//
496// Unless required by applicable law or agreed to in writing, software
497// distributed under the License is distributed on an "AS IS" BASIS,
498// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
499// See the License for the specific language governing permissions and
500// limitations under the License.
501// ----------------------------- END-OF-FILE ----------------------------------
502
503/** @} */
504/** @} */
505/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
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:551
CopyMoveState::Enum copyMoveState(bslmf::MatchAnyType)
bool operator==(const AllocBitwiseMoveableTestType &lhs, const AllocBitwiseMoveableTestType &rhs)
Any type can be converted into this type.
Definition bslmf_matchanytype.h:150
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:413
static bool isUnknown(const TYPE &v)
Definition bsltf_copymovestate.h:407
static Enum get(const TYPE &obj)
Definition bsltf_copymovestate.h:364
static bool isCopiedInto(const TYPE &v)
Definition bsltf_copymovestate.h:376
static bool isMovedInto(const TYPE &v)
Definition bsltf_copymovestate.h:395
static bool isValid(Enum val)
Definition bsltf_copymovestate.h:418
static bool isOriginal(const TYPE &v)
Definition bsltf_copymovestate.h:401
static bool isCopiedNonconstInto(const TYPE &v)
Definition bsltf_copymovestate.h:382
static bool isCopiedConstInto(const TYPE &v)
Definition bsltf_copymovestate.h:370
static bool isMovedFrom(const TYPE &v)
Definition bsltf_copymovestate.h:389