value-ptr lite: A C++ smart-pointer with value semantics for C++98, C++11 and later
Contents
- Example usage
- In a nutshell
- Dependencies
- Installation
- Synopsis
- Reported to work with
- Building tests and examples
- Other value_ptr implementations
- Notes and references
- Appendix
Pimpl example usage
// in header file:
#include "nonstd/value_ptr.hpp"
// Thanks to value_ptr we get value semantics for free:
struct Widget
{
Widget( int x );
int next();
struct Pimpl;
nonstd::value_ptr<Pimpl> ptr;
};
// in source file:
struct Widget::Pimpl
{
int x;
Pimpl( int v ) : x( v ) {}
int next() { return ++x; }
};
Widget::Widget( int x ) : ptr( Widget::Pimpl( x ) ) {} // or: ptr( x )
int Widget::next() { return ptr->next(); }
int main()
{
Widget w1( 42 );
Widget w2( w1 );
assert( w1.next() == 43 );
assert( w2.next() == 43 );
}
In a nutshell
value-ptr lite is a single-file header-only library to bring value semantics to heap resources. In certain situations, such as with the pimpl idiom in the example above, a pointer must be used while value semantics would be prefered. This is where value_ptr
comes into play. A value_ptr
is similar to a std::optional
in many respects and one could say a value_ptr
is more value than pointer.
This work is inspired on value_ptr
by Gaetano Checinski [1] and on impl_ptr
by Andrey Upadyshev [2].
Features and properties of value-ptr lite are ease of installation (single header), freedom of dependencies other than the standard library. value-ptr lite shares the approach to in-place tags with any-lite, optional-lite and with variant-lite and these libraries can be used together.
Limitations of value-ptr lite are ... .
License
value-ptr lite is distributed under the Boost Software License.
Dependencies
value-ptr lite has no other dependencies than the C++ standard library.
Installation
value-ptr lite is a single-file header-only library. Put value_ptr.hpp
in the include folder directly into the project source tree or somewhere reachable from your project.
Synopsis
Contents
- Types in namespace nonstd
- Interface of value-ptr lite
- Non-member functions for value-ptr lite
- Configuration macros
Types in namespace nonstd
Purpose | [1] | [2] | Type | Notes |
---|---|---|---|---|
Smart pointer with value semantics |
✓ | ✓ | class value_ptr | [2]: impl_ptr |
Error reporting | – | – | class bad_value_access | |
In-place construction | – | – | struct in_place_tag | |
– | – | in_place | select type or index for in-place construction | |
– | – | nonstd_lite_in_place_type_t( T) | macro for alias template in_place_type_t<T> | |
– | – | nonstd_lite_in_place_index_t( T ) | macro for alias template in_place_index_t<T> |
Interface of value-ptr lite
value_ptr
Class Kind | [1] | [2] | std | Type / Method | Note / Result |
---|---|---|---|---|---|
Value types | ✓ | ✓ | element_type | ||
✓ | ✓ | pointer | |||
– | – | reference | |||
– | – | const_pointer | |||
– | – | const_reference | |||
Lifetime types | ✓ | – | cloner_type | [2]: copier_type | |
✓ | ✓ | deleter_type | |||
Construction | ✓ | ✓ | value_ptr() noexcept | ||
– | ✓ | C++11 | value_ptr( std::nullptr_t ) noexcept | ||
✓ | – | value_ptr( pointer p ) noexcept | |||
✓ | ✓ | value_ptr( value_ptr const & other ) | |||
✓ | ✓ | C++11 | value_ptr( value_ptr && other ) noexcept | ||
✓ | 1 | value_ptr( element_type const & value ) | |||
✓ | 1 | C++11 | value_ptr( element_type && value ) noexcept | ||
– | – | C++11 | template< class... Args > explicit value_ptr( in_place_type_t(T), Args&&... args ) |
||
– | – | C++11 | template< class U, class... Args > explicit value_ptr( in_place_type_t(T), std::initializer_list<U> il, Args&&... args ) |
||
✓ | – | value_ptr( cloner_type const & cloner ) | |||
✓ | – | C++11 | value_ptr( cloner_type && cloner ) noexcept | ||
– | – | value_ptr( deleter_type const & deleter ) | |||
– | – | C++11 | value_ptr( deleter_type && deleter ) noexcept | ||
✓ | – | C++11 | template< class V, class ClonerOrDeleter > value_ptr( V && value, ClonerOrDeleter && cloner_or_deleter ) |
||
– | – | <C++11 | template< class V, class ClonerOrDeleter > value_ptr( V const & value, ClonerOrDeleter const & cloner_or_deleter ) |
||
✓ | – | C++11 | template< class V, class C, class D > value_ptr( V && value, C && cloner, D && deleter ) |
||
– | – | <C++11 | template< class V, class C, class D > value_ptr( V const & value, C const & cloner, D const & deleter ) |
||
Destruction | – | – | C++11 | ~value_ptr() | |
Assignment | – | – | C++11 | value_ptr & operator=( std::nullptr_t ) noexcept | |
– | – | value_ptr & operator=( T const & value ) | |||
– | – | C++11 | template< class U, ... > value_ptr & operator=( U && value ) |
||
– | ✓ | value_ptr & operator=( value_ptr const & rhs ) | |||
– | ✓ | C++11 | value_ptr & operator=( value_ptr && rhs ) noexcept | ||
Emplace | – | – | C++11 | template< class... Args > void emplace( Args&&... args ) |
|
– | – | C++11 | template< class U, class... Args > void emplace( std::initializer_list<U> il, Args&&... args ) |
||
Observers | ✓ | ✓ | pointer get() noexcept | ||
✓ | ✓ | cloner_type & get_cloner() noexcept | [2]: get_copier() | ||
✓ | ✓ | deleter_type & get_deleter() noexcept | |||
✓ | ✓ | reference operator*() const | |||
✓ | ✓ | pointer operator->() const noexcept | |||
✓ | ✓ | C++11 | explicit operator bool() const noexcept | ||
– | – | <C++11 | operator safe_bool() const noexcept | ||
– | – | bool has_value() const nsvp_noexcept | |||
– | – | element_type const & value() const | |||
– | – | element_type & value() | |||
– | – | C++11 | template< class U > constexpr element_type value_or( U && v ) const |
||
– | – | <C++11 | template< class U > constexpr element_type value_or( U const & v ) const |
||
Modifiers | ✓ | ✓ | pointer release() noexcept | ||
– | – | void reset( pointer p = pointer() ) noexcept | |||
– | ✓ | void swap( value_ptr & other ) noexcept |
Notes:
- [2] has various converting constructors.
Non-member functions for value-ptr lite
Kind | [1] | [2] | std | Function |
---|---|---|---|---|
Relational operators | – | ✓ | template< ... > bool operator op( value_ptr<...> const & lhs, value_ptr<...> const & rhs ) |
|
– | ✓ | C++11 | template< ... > bool operator op( value_ptr<...> const & lhs, std::nullptr_t ) |
|
– | ✓ | C++11 | template< ... > bool operator op( std::nullptr_t, value_ptr<...> const & rhs ) |
|
– | – | template< ... > bool operator op( value_ptr<...> const & lhs, T const & value ) |
||
– | – | template< ... > bool operator op( T const & value, value_ptr<...> const & rhs ) |
||
Swap | – | ✓ | template< class T, class C, class D > void swap( value_ptr<T,C,D> & x, value_ptr<T,C,D> & y ) noexcept(...) |
|
Create | – | – | <C++11 | template< class T, class C, class D > value_ptr<T,C,D> make_value( T const & v ) |
– | – | C++11 | template< class T > value_ptr< typename std::decay<T>::type > make_value( T && v ) |
|
– | – | C++11 | template< class T, class...Args > value_ptr<T,C,D> make_value( Args&&... args ) |
|
– | – | C++11 | template< class T, class U, class... Args > value_ptr<T,C,D> make_value( std::initializer_list<U> il, Args&&... args ) |
|
Hash | – | ✓ | C++11 | template< class T > class hash< nonstd::value_ptr<T,C,D> > |
Configuration macros
Standard selection macro
-Dnsvp_CPLUSPLUS=199711L
Define this macro to override the auto-detection of the supported C++ standard, if your compiler does not set the __cpluplus
macro correctly.
Compare pointers
-Dnsvp_CONFIG_COMPARE_POINTERS=0
Define this to 1 to compare value_ptr
's pointer instead of the content it's pointing to. Default is 0.
Disable exceptions
-Dnsvp_CONFIG_NO_EXCEPTIONS=0
Define this to 1 if you want to compile without exceptions. If not defined, the header tries and detect if exceptions have been disabled (e.g. via -fno-exceptions
). Default is undefined.
Reported to work with
The table below mentions the compiler versions value-ptr lite is reported to work with.
OS | Compiler | Versions |
---|---|---|
Windows | Clang/LLVM | ? |
GCC | 5.2.0, 6.3.0 | |
Visual C++ (Visual Studio) |
8 (2005), 10 (2010), 11 (2012), 12 (2013), 14 (2015, 2017) |
|
GNU/Linux | Clang/LLVM | 3.1.0 - 4.0.0 (Wandbox) |
GCC | 4.4.7 - 7.1.0 (Wandbox) | |
OS X | ? | ? |
Building tests and examples
To build the tests and examples you need:
- Buck or CMake version 2.8.12 or later to be installed and in your PATH.
- A suitable compiler.
The lest test framework is included in the test folder.
The following steps assume that the value_ptr lite source code has been cloned into a directory named value-ptr-lite
.
Buck
To run the tests and examples:
value-ptr-lite> buck run test
value-ptr-lite> buck run example:01-pimpl
value-ptr-lite> buck run example:02-tree
CMake
-
Create a directory for the build outputs for a particular architecture. Here we use
value-ptr-lite/build
.value-ptr-lite> mkdir build && cd build
-
Configure CMake to use the compiler of your choice (run
cmake --help
for a list).value-ptr-lite/build> cmake -G "Unix Makefiles" [see 3. below] ..
-
Optional. You can control above configuration through the following options:
-DVALUE_PTR_LITE_BUILD_TEST=ON
: build the tests for lest, default off-DVALUE_PTR_LITE_BUILD_EXAMPLE=ON
: build the examples, default off-DVALUE_PTR_LITE_COLOURISE_TEST=ON
: use colour for pass, fail, default off
-
Build the test suite. With Visual Studio, append the configuration as
--config Debug
or--config Release
.value-ptr-lite/build> cmake --build .
-
Run the test suite.
value-ptr-lite/build> ctest -V
All tests should pass, indicating your platform is supported and you are ready to use value-ptr lite. See the table with supported types and functions.
Other value-ptr implementations
- LoopPerfect. valuable: A C++ smart-pointer with value-semantics (C++14).
- Search value ptr on GitHub.
Notes and references
[1] Gaetano Checinski. value_ptr — The Missing C++ Smart-pointer (GitHub). May 2017.
[2] Andrey Upadyshev. PIMPL, Rule of Zero and Scott Meyers (GitHub). December 29, 2015.
Appendix
A.1 Compile-time information
The version of value-ptr lite is available via tag [.version]
. The following tags are available for information on the compiler and on the C++ standard library used: [.compiler]
, [.stdc++]
, [.stdlanguage]
and [.stdlibrary]
.
A.2 Value-ptr lite test specification
value_ptr: Allows to default construct an empty value_ptr
value_ptr: Allows to explicitly construct a disengaged, empty value_ptr via nullptr
value_ptr: Allows to default construct an empty value_ptr with a non-default-constructible
value_ptr: Allows to copy-construct from empty value_ptr
value_ptr: Allows to copy-construct from non-empty value_ptr
value_ptr: Allows to move-construct from value_ptr (C++11)
value_ptr: Allows to copy-construct from literal value
value_ptr: Allows to copy-construct from value
value_ptr: Allows to move-construct from value (C++11)
value_ptr: Allows to in-place construct from literal value (C++11)
value_ptr: Allows to in-place copy-construct from value (C++11)
value_ptr: Allows to in-place move-construct from value (C++11)
value_ptr: Allows to in-place copy-construct from initializer-list (C++11)
value_ptr: Allows to in-place move-construct from initializer-list (C++11)
value_ptr: Allows to construct from pointer to value
value_ptr: Allows to assign nullptr to disengage (C++11)
value_ptr: Allows to copy-assign from/to engaged and disengaged value_ptr-s
value_ptr: Allows to move-assign from/to engaged and disengaged value_ptr-s (C++11)
value_ptr: Allows to copy-assign from literal value
value_ptr: Allows to copy-assign from value
value_ptr: Allows to move-assign from value (C++11)
value_ptr: Allows to copy-emplace content from arguments (C++11)
value_ptr: Allows to move-emplace content from arguments (C++11)
value_ptr: Allows to copy-emplace content from intializer-list and arguments (C++11)
value_ptr: Allows to move-emplace content from intializer-list and arguments (C++11)
value_ptr: Allows to construct and destroy via user-specified cloner and deleter
value_ptr: Allows to construct via user-specified cloner with member data
value_ptr: Allows to obtain pointer to value via operator->()
value_ptr: Allows to obtain value via operator*()
value_ptr: Allows to obtain moved-value via operator*()
value_ptr: Allows to obtain engaged state via operator bool()
value_ptr: Allows to obtain engaged state via has_value()
value_ptr: Allows to obtain value via value()
value_ptr: Allows to obtain value or default via value_or()
value_ptr: Allows to obtain moved-default via value_or() (C++11)
value_ptr: Throws bad_value_access at disengaged access
value_ptr: Allows to release its content
value_ptr: Allows to clear its content (reset)
value_ptr: Allows to replace its content (reset)
value_ptr: Allows to swap with other value_ptr (member)
value_ptr: Allows to swap with other value_ptr (non-member)
value_ptr: Provides relational operators (non-member, pointer comparison: nsvp_CONFIG_COMPARE_POINTERS!=0)
value_ptr: Provides relational operators (non-member, value comparison: nsvp_CONFIG_COMPARE_POINTERS==0)
value_ptr: Provides relational operators (non-member, mixed value comparison: nsvp_CONFIG_COMPARE_POINTERS==0)
make_value: Allows to copy-construct value_ptr
make_value: Allows to move-construct value_ptr (C++11)
make_value: Allows to in-place copy-construct value_ptr from arguments (C++11)
make_value: Allows to in-place move-construct value_ptr from arguments (C++11)
make_value: Allows to in-place copy-construct value_ptr from initializer-list and arguments (C++11)
make_value: Allows to in-place move-construct value_ptr from initializer-list and arguments (C++11)
std::hash<>: Allows to obtain hash (C++11)