|
| bslalg::NothrowMovableWrapper< TYPE >::NothrowMovableWrapper () |
|
| bslalg::NothrowMovableWrapper< TYPE >::NothrowMovableWrapper (bsl::allocator_arg_t, const allocator_type &alloc) |
|
| bslalg::NothrowMovableWrapper< TYPE >::NothrowMovableWrapper (const TYPE &val) |
|
| bslalg::NothrowMovableWrapper< TYPE >::NothrowMovableWrapper (bsl::allocator_arg_t, const allocator_type &alloc, const TYPE &val) |
|
| bslalg::NothrowMovableWrapper< TYPE >::NothrowMovableWrapper (bslmf::MovableRef< TYPE > val) |
| Wrap the specified val , using TYPE s move constructor.
|
|
| bslalg::NothrowMovableWrapper< TYPE >::NothrowMovableWrapper (bsl::allocator_arg_t, const allocator_type &alloc, bslmf::MovableRef< TYPE > val) |
|
| bslalg::NothrowMovableWrapper< TYPE >::NothrowMovableWrapper (const NothrowMovableWrapper &original) |
|
| bslalg::NothrowMovableWrapper< TYPE >::NothrowMovableWrapper (bsl::allocator_arg_t, const allocator_type &alloc, const NothrowMovableWrapper &original) |
|
| bslalg::NothrowMovableWrapper< TYPE >::NothrowMovableWrapper (bslmf::MovableRef< NothrowMovableWrapper > original) BSLS_KEYWORD_NOEXCEPT |
|
| bslalg::NothrowMovableWrapper< TYPE >::NothrowMovableWrapper (bsl::allocator_arg_t, const allocator_type &alloc, bslmf::MovableRef< NothrowMovableWrapper > original) |
|
| bslalg::NothrowMovableWrapper< TYPE >::~NothrowMovableWrapper () |
| Destroy this object, invoking TYPE s destructor.
|
|
ValueType & | bslalg::NothrowMovableWrapper< TYPE >::unwrap () |
|
allocator_type | bslalg::NothrowMovableWrapper< TYPE >::get_allocator () const |
|
ValueType const & | bslalg::NothrowMovableWrapper< TYPE >::unwrap () const |
| Return a reference offering const access to the wrapped object.
|
|
Outline
Purpose
Provide a wrapper that asserts a noexcept move constructor.
Classes
- See also
- bslalg_movablewrapperutil
Description
This component provides a wrapper class template bslalg::NothrowMovableWrapper<TYPE>
holding an object of TYPE
and providing no other functionality other than returning the wrapped object. The use of this class communicates to specific clients (see bslstl_function ) that the wrapped object should be treated as-if it has a noexcept
move constructor, even in C++03, where noexcept
does not exist. The client might, for example, move the object using efficient, non-exception-safe logic rather than, e.g., copying the object or storing it in heap memory so that its pointer can be moved. The behavior is undefined if the move constructor is invoked and does throw; typically resulting in terminate
being invoked.
Usage
Example 1
In this example, we define a class template, CountedType<TYPE>
, a wrapper around TYPE
that counts the number of extant CountedType
objects. We begin by defining the static count member along with the single value member:
template <class TYPE>
class CountedType {
static int s_count;
TYPE d_value;
Because of externally-imposed requirements, the move constructor for CountedType
must provide the strong guarantee; i.e., if the move constructor of TYPE
throws an exception, then the moved-from CountedType
object must be left unchanged. To support this requirement, we next define a private static function, MoveIfNoexcept
, similar to the standard std::move_if_noexcept
, that returns a movable reference if its argument is no-throw move constructible and a const lvalue reference otherwise:
template <class TP>
static typename
MoveIfNoexcept(TP& x);
Definition bslmf_movableref.h:751
Definition bslmf_conditional.h:120
We next finish out the class definition with a constructor, copy constructor, move constructor, destructor, and member functions to retrieve the count and value:
public:
static int count() { return s_count; }
CountedType(const TYPE& val);
CountedType(const CountedType& original);
~CountedType() { --s_count; }
TYPE& value() { return d_value; }
const TYPE& value() const { return d_value; }
};
Next, we implement MoveIfNoexcept
, which calls move
on its argument, allowing it to convert back to an lvalue if the return type is an lvalue reference:
template <class TYPE>
template <class TP>
inline typename
CountedType<TYPE>::MoveIfNoexcept(TP& x)
{
}
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1060
Next, we implement the value constructor and copy constructor, which simply copy their argument into the d_value
data members and increment the count:
template <class TYPE>
CountedType<TYPE>::CountedType(const TYPE& val) : d_value(val)
{
++s_count;
}
template <class TYPE>
CountedType<TYPE>::CountedType(const CountedType& original)
: d_value(original.d_value)
{
++s_count;
}
We're now ready implement the move constructor. Logically, we would simply move the value from original
into the d_value
member of *this
, but an exception thrown by TYPE
s move constructor would leave original
in a (valid but) unspecified state, violating the strong guarantee. Instead, we move the value only if we know that the move will succeed; otherwise, we copy it. This behavior is facilitated by the MoveIfNoexcept
function defined above:
template <class TYPE>
: d_value(
MoveIfNoexcept(
bslmf::MovableRefUtil::access(original).d_value))
{
++s_count;
}
Definition bdlbb_blob.h:576
Finally, we define the s_count
member to complete the class implementation:
template <class TYPE>
int CountedType<TYPE>::s_count = 0;
To test the CountedType
class template, assume a simple client type, SomeType
that makes it easy to detect if it was move constructed. SomeType
holds an int
value that is set to -1 when it is moved from, as shown here:
class SomeType {
int d_value;
public:
SomeType(int v = 0) : d_value(v) { }
SomeType(const SomeType& original) : d_value(original.d_value) { }
: d_value(
bslmf::MovableRefUtil::access(original).d_value)
int value() const { return d_value; }
};
static t_TYPE & access(t_TYPE &ref) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1032
Notice that SomeType
neglected to declare its move constructor as noexcept
. This might be an oversight or it could be an old class that predates both noexcept
and the bsl::is_nothrow_move_constructible
trait. It is even be possible that the move constructor might throw (though, of course, it doesn't in this simplified example). Regardless, the effect is that move-constructing a CountedType<SomeType>
will result in the move constructor actually performing a copy:
void main()
{
CountedType<SomeType> obj1(1);
assert(1 == obj1.value().value());
assert(1 == obj2.value().value());
For the purpose of this example, we can be sure that SomeThing
will not throw on move, at least not in our application. In order to obtain the expected move optimization, we next wrap our 'SomeType in a bslalg::NothrowMovableWrapper
:
CountedType<bslalg::NothrowMovableWrapper<SomeType> >
obj3(SomeType(3));
CountedType<bslalg::NothrowMovableWrapper<SomeType> >
assert(-1 == obj3.value().unwrap().value());
assert(3 == obj4.value().unwrap().value());
}
◆ get_allocator()
Return the allocator used to construct this object. Note that this method will fail to instantiate unless TYPE
is allocator-aware.
◆ NothrowMovableWrapper() [1/10]
◆ NothrowMovableWrapper() [2/10]
Value-initialize the object wrapped by *this
. For allocator-aware TYPE
, optionally specify an alloc
(e.g., the address of a bslma::Allocator
object) to supply memory; otherwise, the default allocator is used.
◆ NothrowMovableWrapper() [3/10]
Move construct from the specified original
wrapper using TYPE
s extended move constructor. Use the specified alloc
(e.g., the address of a bslma::Allocator
object) to supply memory. Note that this constructor will not be selected by overload resolution unless TYPE
is allocator aware.
◆ NothrowMovableWrapper() [4/10]
Wrap the specified val
, using TYPE
s extended move constructor. Use the specified alloc
(e.g., the address of a bslma::Allocator
object) to supply memory. Note that this constructor will not be selected by overload resolution unless TYPE
is allocator aware.
◆ NothrowMovableWrapper() [5/10]
Copy construct from the specified original
wrapper using TYPE
s extended copy constructor. Use the specified alloc
(e.g., the address of a bslma::Allocator
object) to supply memory. Note that this constructor will not be selected by overload resolution unless TYPE
is allocator aware.
◆ NothrowMovableWrapper() [6/10]
◆ NothrowMovableWrapper() [7/10]
◆ NothrowMovableWrapper() [8/10]
◆ NothrowMovableWrapper() [9/10]
Copy construct from the specified original
wrapper using TYPE
s copy constructor.
◆ NothrowMovableWrapper() [10/10]
Wrap the specified val
, using TYPE
s (possibly extended) copy constructor. For allocator-aware TYPE
, optionally specify an alloc
(e.g., the address of a bslma::Allocator
object) to supply memory; otherwise, the default allocator is used.
◆ unwrap() [1/2]
Return a reference offering modifiable access to the wrapped object.
◆ unwrap() [2/2]
◆ ~NothrowMovableWrapper()