BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsltf_copymovestate

Detailed Description

Outline

Purpose

Provide an enumeration of copy/move state, including unsupported.

Classes

See also
bsltf_copymovetracker

Description

This component provides a struct, bsltf::CopyMoveState, which serves as a namespace for enumerating the copy and move state of an object, including an unknown value indicating that the test type does not support tracking this information. A test type can, using a single instance of this enum track whether the object was most recently copied into, moved into, or moved from.

In instances where more than one operatation needs to be tracked (i.e., the object was copied into, then moved from), the logical-OR of multiple enumerators can be stored in a single variable, but doing so does not preserve the order of the operations nor whether any operation occured more than once; if such information is needed, multiple instances of this enum can be used.

The CopyMoveState namespace also provides a toAscii method that converts an enumerator into its name represented as a null-terminated ASCII string.

Enumerators

Name Description
---------------------- ---------------------------------------------------
e_ORIGINAL Original value; object was not copied or moved into
e_COPIED_INTO Object was copied into
e_COPIED_CONST_INTO Object was copied into from a const reference
e_COPIED_NONCONST_INTO Object was copied into from a non-const reference
e_MOVED_INTO Object was moved into (from a movable reference)
e_MOVED_FROM Object was moved from
e_UNKNOWN Object does not track copy/move history

All of the enumerators have unique values. The e_ORIGINAL enumerator has value 0 (no bits set). The values for e_COPIED_CONST_INTO and e_COPIED_NONCONST_INTO each have the e_COPIED_INTO bit set as well as one other bit. The remaining enumerators have one bit set each, sharing no bits with any of the other enumerators.

When converted to bool, e_ORIGINAL yields false whereas the rest yield true. When e_UNKNOWN is not used, this conversion makes it easy create a binary test of whether an object was copied or moved.

Usage

This section illustrates intended use of this component.

Example 1: Tracking an object's history

In this example, we show how CopyMoveState can be used to track the most recent copy or move operation applied to an object.

First, we define a TrackedValue type that contains an integer value and a CopyMoveState

#include <cstring>
struct TrackedValue {
int d_value;
bsltf::CopyMoveState::Enum d_copyMoveState;
Enum
Definition bsltf_copymovestate.h:222

Next, we define a value constructor that indicates that the object was neither copied into, moved into, nor moved from:

TrackedValue(int v = 0) // IMPLICIT
: d_value(v)
, d_copyMoveState(bsltf::CopyMoveState::e_ORIGINAL) { }
Definition bsltf_allocargumenttype.h:92

Next, we define a copy constructor that records the fact that the object was copied into. As in the case of most copy constructors, the original is accessed through a const reference, and the copy/moved state reflects that fact.

TrackedValue(const TrackedValue& original)
: d_value(original.d_value)
, d_copyMoveState(bsltf::CopyMoveState::e_COPIED_CONST_INTO) { }

Next, we define a move constructor that records both that the object being constructed was moved into, but also that the original object was moved from.

TrackedValue(bslmf::MovableRef<TrackedValue> original)
: d_value(bslmf::MovableRefUtil::access(original).d_value)
, d_copyMoveState(bsltf::CopyMoveState::e_MOVED_INTO)
{
TrackedValue& originalRef = original;
originalRef.d_value = -1;
originalRef.d_copyMoveState = bsltf::CopyMoveState::e_MOVED_FROM;
}
Definition bslmf_movableref.h:751
Definition bdlbb_blob.h:576
@ e_MOVED_FROM
Definition bsltf_copymovestate.h:230

Next, we declare the destructor and assignment operators, but, for the purpose of this example, we don't need to see their implementations:

//! ~TrackedValue() = default;
TrackedValue& operator=(const TrackedValue&);
TrackedValue& operator=(bslmf::MovableRef<TrackedValue>);

Then, we define accessors for the value and copy/move state.

int value() const { return d_value; }
bsltf::CopyMoveState::Enum copyMoveState() const
{ return d_copyMoveState; }

Now, outside of the class definition or (better yet) as a hidden friend function, we define an ADL customization point used to retrieve the copy/move state of the tracked value. This free function will be called in generic code that doesn't know whether the type it's working with has a copyMoveState accessor; a default is provided for types that don't:

friend bsltf::CopyMoveState::Enum copyMoveState(const TrackedValue& v)
{
return v.copyMoveState();
}
};

Finally, we test our TrackedValue class by creating an object, copying it, and moving it. After each step, we test that each object's copy/move state is as expected. Note that e_COPIED_INTO names a bit that is set in both of the other e_COPIED_* enumerators. At the end, we verify that the copy/move state is correctly converted to a string by the toAscii method and that the copy/move state of a plain int is always "e_UNKNOWN".

int main()
{
typedef bsltf::CopyMoveState Cms;
TrackedValue tv1(42);
assert(42 == tv1.value());
assert(Cms::e_ORIGINAL == tv1.copyMoveState());
assert(Cms::get(tv1) == tv1.copyMoveState());
TrackedValue tv2(tv1); // Copy
assert(42 == tv2.value());
assert(Cms::e_COPIED_CONST_INTO == tv2.copyMoveState());
assert(Cms::e_COPIED_INTO & tv2.copyMoveState());
TrackedValue tv3(bslmf::MovableRefUtil::move(tv1)); // Move
assert(42 == tv3.value());
assert(Cms::e_MOVED_INTO == tv3.copyMoveState());
assert(-1 == tv1.value());
assert(Cms::e_MOVED_FROM == tv1.copyMoveState());
assert(0 == std::strcmp("MOVED_FROM",
Cms::toAscii(tv1.copyMoveState())));
assert(Cms::e_UNKNOWN == Cms::get(5)); // 'int' doesn't track state
}
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1060
Definition bsltf_copymovestate.h:219