2.10.0
Freundlich's C++ toolkit
Classes | Functions
fcppt.smart_pointers

Description

unique_ptr, shared_ptr and weak_ptr without default constructors.

Introduction

A smart pointer is a class that takes ownership over a pointer, freeing the object pointed to when the smart pointer is destroyed. Such a smart pointer resides on the stack, so freeing is done automatically.

fcppt provides all smart pointers that are also in C++11 with the following changes:

Smart pointer types

fcppt provides three smart pointer classes, each with their own trade-offs.

Class name

Description

fcppt::unique_ptr

A move-only smart pointer that is the unique owner of an object. This should be the default choice of smart pointer.

fcppt::shared_ptr

Manages objects using a shared count. Every shared ptr pointing to the same object increases the shared count by one. The object will only be destroyed when all shared ptrs have been destroyed.

fcppt::weak_ptr

A weak reference to an object managed by shared ptrs. This smart pointer doesn't contribute to the shared count and can be used to observe if shared ptrs are still alive.

Shared Pointers

Multiple fcppt::shared_ptr that point to the same object share ownership by internally managing a shared count that counts how many shared ptrs are left. This shared count will be increased whenever a shared ptr is copied and decreased when one is destroyed.

For most use cases, unique ptrs should be preferred over shared ptrs.

The general traits of a shared ptr are as follows:

Here is a simple example using shared pointers.

// Typedef a shared_ptr to in int
int
> int_ptr;
// Objects of this class should share ownership of int_ptrs
class owner
{
public:
explicit
owner(
int_ptr _ptr
)
:
ptr_(
_ptr
)
{
}
private:
int_ptr ptr_;
};
void
shared_ptr_example()
{
// Creates a shared_ptr
int_ptr const ptr(
new int(42)
);
// Copies the ownership to owner1, increasing the shared count to 2
owner owner1(
ptr
);
// Copies from owner1 to owner2, increasing the shared count to 3
owner owner2(
owner1
);
// The destruction of owner2, owner1 and ptr will free the int
}
}

Using make_shared

fcppt::make_shared_ptr can be used to place an object allocated via new into the same memory block as the shared count managed by the shared ptrs. Another reason to use this function is to avoid memory leaks, that can happen due to C++'s unspecified order of evaluation, if you are not careful.

Here is an example of how not using fcppt::make_shared_ptr can lead to a memory leak.

// Create a function that takes ownership of an int_ptr, but also takes another
// argument.
void
take_pointer(
int_ptr,
bool
)
{
//
}
// This function will be used to provide a bool value for take_pointer, but it
// throws when executed.
bool
throw_something()
{
throw std::runtime_error("test");
}
void
wrong()
{
// The order in which function arguments and their sub-expressions are
// evaluated is unspecified. So it might be possible that they are
// evaluated as follows:
// a) new int(100)
// b) throw_something()
// c) int_ptr(...) is never reached and we have a leak
take_pointer(
int_ptr(
new int (100)
),
throw_something()
);
}

Using fcppt::make_shared_ptr eliminates this problem and also makes the dynamic memory management of the shared ptrs more efficient.

void
{
take_pointer(
int
>(
100
),
throw_something()
);
}

Weak Pointers

A weak pointer can be used to keep track of the shared ptrs to one object without contributing to the shared count. We can then observe if a shared ptr is still alive. This can also be used to break cycles.

A weak ptr can be used as follows:

typedef
int
>
weak_int_ptr;
typedef
int
>
shared_int_ptr;
weak_int_ptr weak_p;
{
shared_int_ptr const int_ptr(
int
>(
42
)
);
// Create a weak_ptr to the shared_ptr
weak_p =
int_ptr;
if(
weak_p.lock().has_value()
)
<< FCPPT_TEXT("A shared ptr is still alive.\n");
}
// Observe if a shared_ptr is still alive. At this point, no
// shared_ptr is alive.
if(
!weak_p.lock().has_value()
)
<< FCPPT_TEXT("No shared ptrs are alive.\n");

Casting Shared Pointers

When casting shared ptrs, using static_cast, dynamic_cast or const_cast directly will not work, because the shared count will not be preserved. Instead, we have to use one of the special functions fcppt::static_pointer_cast, fcppt::dynamic_pointer_cast or fcppt::const_pointer_cast.

Here is an example:

struct base
{
virtual ~base()
{
}
};
struct derived
:
base
{};
void
cast()
{
typedef
base
>
base_ptr;
base_ptr ptr(
new derived()
);
typedef
derived
>
derived_ptr;
derived_ptr
> dptr(
derived
>(
ptr
)
);
if(
dptr.has_value()
)
<< FCPPT_TEXT("ptr points to a derived.\n");
}

Unique Pointers

In contrast to a shared ptr, a unique ptr always is the sole owner of an object.

The general traits of a unique ptr are as follows:

Using Unique Pointers

The first thing to note is that unique ptrs are an excellent candidate for factory functions. They don't impose overly strict ownership requirements like shared ptr does. However, unique ptrs can be converted into shared ptrs as desired. The following example shows how such a factory can be created.

int
> unique_int_ptr;
// Create a unique_ptr factory
unique_int_ptr
int_ptr_factory()
{
// make_unique_ptr is a factory function to make a unique_ptr An
// rvalue is returned here, so no moving is necessary.
return
int
>(
42
);
}

The return of make_unique_ptr doesn't require a move, because it returns an rvalue.

The factory can be used as follows:

void
int_ptr_arg(
unique_int_ptr &&ptr
)
{
<< *ptr
<< FCPPT_TEXT('\n');
}
void
{
int_ptr_arg(
int_ptr_factory()
);
}

Again, there is no move required because the factory also returns an rvalue.

Moving Unique Pointers

The next example shows when a move is required. This is generally true when an lvalue is involved (which means a named object here). The reason for this is to ensure that a unique ptr doesn't accidentally get its object disowned.

unique_int_ptr
test2()
{
// ptr is a named object
unique_int_ptr ptr(
int
>(
42
)
);
// ptr must be moved here to take ownership away from it
return
ptr;
}

Consider the following example where an implicit move would be very dangerous:

void
test3()
{
unique_int_ptr ptr(
int
>(
42
)
);
// Implicit move is not allowed
/*
int_ptr_arg(
ptr
);
*/
// Make the move explicit
int_ptr_arg(
std::move(
ptr
)
);
// ptr is now the null pointer
<< ptr.get_pointer()
<< FCPPT_TEXT('\n');
}

Converting Unique Pointers

Unique pointers are not implicitly convertible to any other unique pointers. To convert a unique pointer to a unique pointer to base, use fcppt::unique_ptr_to_base.

struct base
{
virtual
~base()
{
}
};
struct dervied
:
base
{
};
void
test4()
{
typedef
base
>
base_ptr;
base_ptr foo(
base
>(
dervied
>()
)
);
}

Similarly, fcppt::unique_ptr_to_const must be used to obtain a unique pointer to a const object.

typedef
int const
>
const_int_ptr;
const_int_ptr foo(
int
>(
42
)
)
);

Const Unique Pointers

fcppt used to provide a scoped_ptr class similar to boost::scoped_ptr that additionally took a deleter. This class has been removed in favor of const unique ptrs.

int
> const scoped_int_ptr;
scoped_int_ptr const ptr(
int
>(
42
)
);

A unique ptr that has been declared const cannot be copied nor moved. Additionally, it can also not be swapped.

Unique Pointers and Pimpl

A unique ptr can also be used to implement the pimpl idiom. When a unique ptr object is defined, the pointed to object doesn't need to be complete. It only has to be complete when the destructor of the unique ptr is instantiated. Therefore, an implementation can be hidden by using unique ptrs as shown in the following example:

class foo_impl;
class foo
{
// Explicitly disable copying
foo
);
public:
foo();
~foo();
private:
// const to disable move
foo_impl
> const impl_;
};

Because foo has an explicitly declared destructor, the destruction of the implementation can be hidden in a source file.

class foo_impl
{
// Something here
};
foo::foo()
:
impl_(
foo_impl
>()
)
{
}
foo::~foo() = default;

Custom Deleters

As previously mentioned, fcppt's smart pointers all take the deleter as a template parameter in order to ensure maximum type safety. Such a deleter must have the following properties:

For some smart pointer over type Type the deleter must be callable with an expression of type Type *. The deleter must ensure to destroy the object if it is not a null pointer.

fcppt's Deleters

fcppt predefines several deleters:

For some invented variable name ptr of type Type * their semantics are as follows:

fcppt::default_deleter delete ptr;
fcppt::c_deleter std::free(ptr);
fcppt::com_deleter if(ptr) ptr->Release();

Deleter example

The following example shows how fcppt::c_deleter can be used to free memory allocated via std::malloc

void,
> void_c_ptr;
void_c_ptr ptr(
std::malloc(
100
)
);

Header files

Header file Description
c_deleter.hpp Contains fcppt::c_deleter.
com_deleter.hpp Contains fcppt::com_deleter.
const_pointer_cast.hpp Contains fcppt::const_pointer_cast.
default_deleter.hpp Contains fcppt::default_deleter.
dynamic_pointer_cast.hpp Contains fcppt::dynamic_pointer_cast.
make_shared_ptr.hpp Contains fcppt::make_shared_ptr.
make_unique_ptr.hpp Contains fcppt::make_unique_ptr.
shared_ptr_fwd.hpp Contains fcppt::shared_ptr's declaration.
shared_ptr_decl.hpp Contains fcppt::shared_ptr's definition.
shared_ptr_impl.hpp Contains the definition of fcppt::shared_ptr's member functions.
shared_ptr.hpp The same as shared_ptr_impl.hpp
static_pointer_cast.hpp Contains fcppt::static_pointer_cast
unique_ptr_fwd.hpp Contains fcppt::unique_ptr's declaration.
unique_ptr_decl.hpp Contains fcppt::unique_ptr's definition.
unique_ptr_impl.hpp Contains the definition of fcppt::unique_ptr's member functions.
unique_ptr.hpp The same as unique_ptr_impl.hpp
unique_ptr_to_base.hpp Contains fcppt::unique_ptr_to_base.
unique_ptr_to_const.hpp Contains fcppt::unique_ptr_to_const.
weak_ptr_fwd.hpp Contains fcppt::weak_ptr's declaration.
weak_ptr_decl.hpp Contains fcppt::weak_ptr's definition.
weak_ptr_impl.hpp Contains the definition of fcppt::weak_ptr's member functions.
weak_ptr.hpp The same as weak_ptr_impl.hpp

Classes

struct  fcppt::c_deleter
 A deleter that uses std::free to destroy an object. More...
 
struct  fcppt::com_deleter
 A deleter that uses the Release member function to destroy an object. More...
 
struct  fcppt::default_deleter
 A deleter that uses delete to destroy an object. More...
 
class  fcppt::enable_shared_from_this< Type >
 Allows an object to obtain a shared ptr to itself. More...
 
class  fcppt::shared_ptr< Type, Deleter >
 A shared pointer class that gets the deleter as a template parameter. More...
 
struct  fcppt::shared_ptr< Type >>
 A hash for fcppt::shared_ptr that hashes pointers. More...
 
class  fcppt::unique_ptr< Type, Deleter >
 A simpler unique_ptr that shouldn't be used as a null pointer. More...
 
class  fcppt::weak_ptr< Type, Deleter >
 A weak reference to an object owned by a shared pointer. More...
 

Functions

template<typename Dest , typename Source >
fcppt::shared_ptr< Dest > fcppt::const_pointer_cast (fcppt::shared_ptr< Source const > const &_ptr)
 Casts an fcppt::shared_ptr using const_cast More...
 
template<typename Dest , typename Source >
fcppt::optional::object< fcppt::shared_ptr< Dest >> fcppt::dynamic_pointer_cast (fcppt::shared_ptr< Source > const &_ptr)
 Casts an fcppt::shared_ptr using dynamic_cast More...
 
template<typename Res , typename... Args>
fcppt::detail::make_shared_wrapper< Res > fcppt::make_shared_ptr (Args &&..._args)
 Like std::make_shared for fcppt::shared_ptr. More...
 
template<typename Res , typename... Args>
fcppt::unique_ptr< Res > fcppt::make_unique_ptr (Args &&..._args)
 Like std::make_unique for fcppt::unique_ptr. More...
 
template<typename Type1 , typename Type2 , typename Deleter >
bool fcppt::operator== (fcppt::shared_ptr< Type1, Deleter > const &left, fcppt::shared_ptr< Type2, Deleter > const &right)
 Compares two shared ptrs for equality. More...
 
template<typename Type1 , typename Type2 , typename Deleter >
bool fcppt::operator!= (fcppt::shared_ptr< Type1, Deleter > const &left, fcppt::shared_ptr< Type2, Deleter > const &right)
 Compares two shared ptrs for inequality. More...
 
template<typename Type1 , typename Type2 , typename Deleter >
bool fcppt::operator< (fcppt::shared_ptr< Type1, Deleter > const &left, fcppt::shared_ptr< Type2, Deleter > const &right)
 Checks if one shared ptr is less than the other. More...
 
template<typename Type , typename Deleter >
void fcppt::swap (fcppt::shared_ptr< Type, Deleter > &left, fcppt::shared_ptr< Type, Deleter > &right)
 Swaps two shared pointers. More...
 
template<typename Ch , typename Traits , typename Type , typename Deleter >
std::basic_ostream< Ch, Traits > & fcppt::operator<< (std::basic_ostream< Ch, Traits > &_stream, fcppt::shared_ptr< Type, Deleter > const &_ptr)
 Outputs a shared pointer. More...
 
template<typename Dest , typename Source >
fcppt::shared_ptr< Dest > fcppt::static_pointer_cast (fcppt::shared_ptr< Source > const &_ptr)
 Casts an fcppt::shared_ptr using static_cast More...
 
template<typename Cast , typename Derived , typename Base , typename Deleter >
fcppt::variant::variadic< fcppt::unique_ptr< Derived, Deleter >, fcppt::unique_ptr< Base, Deleter >> fcppt::unique_ptr_dynamic_cast (fcppt::unique_ptr< Base, Deleter > &&_other) noexcept
 Casts a unique_ptr to a derived class. More...
 
template<typename Type >
fcppt::optional::object< fcppt::unique_ptr< Type >> fcppt::unique_ptr_from_std (std::unique_ptr< Type > &&_ptr)
 Converts a std::unique_ptr to an fcppt unique ptr. More...
 
template<typename Base , typename Derived , typename Deleter >
fcppt::unique_ptr< Base, Deleter > fcppt::unique_ptr_to_base (fcppt::unique_ptr< Derived, Deleter > &&_other) noexcept
 Casts a unique_ptr to a base class. More...
 
template<typename Type , typename Deleter >
fcppt::unique_ptr< Type const, Deleter > fcppt::unique_ptr_to_const (fcppt::unique_ptr< Type, Deleter > &&_other) noexcept
 Casts a unique_ptr to a const unique_ptr. More...
 
template<typename Type1 , typename Type2 , typename Deleter >
bool fcppt::operator< (fcppt::weak_ptr< Type1, Deleter > const &left, fcppt::weak_ptr< Type2, Deleter > const &right) noexcept
 Checks if one weak ptr is less than the other. More...
 
template<typename Type , typename Deleter >
void fcppt::swap (fcppt::weak_ptr< Type, Deleter > &left, fcppt::weak_ptr< Type, Deleter > &right) noexcept
 Swaps two weak pointers. More...
 

Function Documentation

◆ const_pointer_cast()

template<typename Dest , typename Source >
fcppt::shared_ptr< Dest> fcppt::const_pointer_cast ( fcppt::shared_ptr< Source const > const &  _ptr)

Casts an fcppt::shared_ptr using const_cast

Casts the pointer stored in _ptr to type U * using const_cast.

Template Parameters
DestThe type of the destination shared_ptr
SourceThe type of the source shared_ptr
Parameters
_ptrThe source shared_ptr
Returns
The converted shared_ptr

◆ dynamic_pointer_cast()

template<typename Dest , typename Source >
fcppt::optional::object< fcppt::shared_ptr< Dest >> fcppt::dynamic_pointer_cast ( fcppt::shared_ptr< Source > const &  _ptr)

Casts an fcppt::shared_ptr using dynamic_cast

Casts the pointer stored in _ptr to type U * using dynamic_cast. This means that T * and U must be members of the same class hierarchy. If the cast succeeds, the resulting shared_ptr will share ownership with the source.

Template Parameters
DestThe type of the destination shared_ptr
SourceThe type of the source shared_ptr
Parameters
_ptrThe source shared_ptr

◆ make_shared_ptr()

template<typename Res , typename... Args>
fcppt::detail::make_shared_wrapper< Res> fcppt::make_shared_ptr ( Args &&...  _args)
inline

Like std::make_shared for fcppt::shared_ptr.

◆ make_unique_ptr()

template<typename Res , typename... Args>
fcppt::unique_ptr< Res> fcppt::make_unique_ptr ( Args &&...  _args)
inline

Like std::make_unique for fcppt::unique_ptr.

◆ operator!=()

template<typename Type1 , typename Type2 , typename Deleter >
bool fcppt::operator!= ( fcppt::shared_ptr< Type1, Deleter > const &  left,
fcppt::shared_ptr< Type2, Deleter > const &  right 
)

Compares two shared ptrs for inequality.

Compares left and right for inequality, comparing their pointers. Pointers to Type1 and to Type2 must be inequality comparable.

Parameters
leftThe left argument
rightThe right argument

◆ operator<() [1/2]

template<typename Type1 , typename Type2 , typename Deleter >
bool fcppt::operator< ( fcppt::weak_ptr< Type1, Deleter > const &  left,
fcppt::weak_ptr< Type2, Deleter > const &  right 
)
noexcept

Checks if one weak ptr is less than the other.

Checks if left is less than right, comparing their pointers with std::less.

Pointers to Type1 and to Type2 must be comparable using std::less.

Parameters
leftThe left argument
rightThe right argument

◆ operator<() [2/2]

template<typename Type1 , typename Type2 , typename Deleter >
bool fcppt::operator< ( fcppt::shared_ptr< Type1, Deleter > const &  left,
fcppt::shared_ptr< Type2, Deleter > const &  right 
)

Checks if one shared ptr is less than the other.

Checks if left is less than right, comparing their pointers with std::less.

Pointers to Type1 and to Type2 must be comparable using std::less.

Parameters
leftThe left argument
rightThe right argument

◆ operator<<()

template<typename Ch , typename Traits , typename Type , typename Deleter >
std::basic_ostream< Ch, Traits>& fcppt::operator<< ( std::basic_ostream< Ch, Traits > &  _stream,
fcppt::shared_ptr< Type, Deleter > const &  _ptr 
)
inline

Outputs a shared pointer.

Outputs _ptr to _stream.

Returns
stream

◆ operator==()

template<typename Type1 , typename Type2 , typename Deleter >
bool fcppt::operator== ( fcppt::shared_ptr< Type1, Deleter > const &  left,
fcppt::shared_ptr< Type2, Deleter > const &  right 
)

Compares two shared ptrs for equality.

Compares left and right for equality, comparing their pointers. Pointers to Type1 and to Type2 must be equality comparable.

Parameters
leftThe left argument
rightThe right argument

◆ static_pointer_cast()

template<typename Dest , typename Source >
fcppt::shared_ptr< Dest> fcppt::static_pointer_cast ( fcppt::shared_ptr< Source > const &  _ptr)

Casts an fcppt::shared_ptr using static_cast

Casts the pointer stored in _ptr to type U * using static_cast.

Template Parameters
DestThe type of the destination shared_ptr
SourceThe type of the source shared_ptr
Parameters
_ptrThe source shared_ptr
Returns
The converted shared_ptr
Warning
The behaviour is undefined if the static_cast is not well formed.

◆ swap() [1/2]

template<typename Type , typename Deleter >
void fcppt::swap ( fcppt::weak_ptr< Type, Deleter > &  left,
fcppt::weak_ptr< Type, Deleter > &  right 
)
noexcept

Swaps two weak pointers.

Swaps left and right

Parameters
leftThe left argument
rightThe right argument

◆ swap() [2/2]

template<typename Type , typename Deleter >
void fcppt::swap ( fcppt::shared_ptr< Type, Deleter > &  left,
fcppt::shared_ptr< Type, Deleter > &  right 
)

Swaps two shared pointers.

Swaps left and right

Parameters
leftThe left argument
rightThe right argument

◆ unique_ptr_dynamic_cast()

template<typename Cast , typename Derived , typename Base , typename Deleter >
fcppt::variant::variadic< fcppt::unique_ptr< Derived, Deleter >, fcppt::unique_ptr< Base, Deleter >> fcppt::unique_ptr_dynamic_cast ( fcppt::unique_ptr< Base, Deleter > &&  _other)
inlinenoexcept

Casts a unique_ptr to a derived class.

Tries to cast the given unique ptr to Derived using the cast function Cast. The result is either a unique_ptr of type Derived, or (if the cast fails) of type Base.

Template Parameters
CastA cast function from fcppt.casts

◆ unique_ptr_from_std()

template<typename Type >
fcppt::optional::object< fcppt::unique_ptr< Type >> fcppt::unique_ptr_from_std ( std::unique_ptr< Type > &&  _ptr)

Converts a std::unique_ptr to an fcppt unique ptr.

◆ unique_ptr_to_base()

template<typename Base , typename Derived , typename Deleter >
fcppt::unique_ptr< Base, Deleter> fcppt::unique_ptr_to_base ( fcppt::unique_ptr< Derived, Deleter > &&  _other)
inlinenoexcept

Casts a unique_ptr to a base class.

◆ unique_ptr_to_const()

template<typename Type , typename Deleter >
fcppt::unique_ptr< Type const, Deleter> fcppt::unique_ptr_to_const ( fcppt::unique_ptr< Type, Deleter > &&  _other)
inlinenoexcept

Casts a unique_ptr to a const unique_ptr.