/value-ptr-lite

value-ptr-lite - A C++ smart-pointer with value semantics for C++98, C++11 and later in a single-file header-only library

Primary LanguageC++Boost Software License 1.0BSL-1.0

value-ptr lite: A C++ smart-pointer with value semantics for C++98, C++11 and later

Language License Build Status Build status Version download Conan

Contents

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

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

Class value_ptr

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:

  1. [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:

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

  1. 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
    
  2. 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] ..
    
  3. 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
  4. Build the test suite. With Visual Studio, append the configuration as --config Debug or --config Release.

     value-ptr-lite/build> cmake --build .
    
  5. 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

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)