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

September 27, 2025 · View on GitHub

Note: You may want to consider using indirect_value lite (p1950) instead of value_ptr lite.

Language License Build Status Version download Conan Vcpkg Try it on godbolt online

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 preferred. 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]TypeNotes
Smart pointer with
value semantics
class value_ptr[2]: impl_ptr
Error reportingclass bad_value_access 
In-place constructionstruct in_place_tag 
 in_placeselect 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]stdType / MethodNote / 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++11value_ptr( std::nullptr_t ) noexcept 
  value_ptr( pointer p ) noexcept 
  value_ptr( value_ptr const & other ) 
 C++11value_ptr( value_ptr && other ) noexcept 
 1 value_ptr( element_type const & value ) 
 1C++11value_ptr( element_type && value ) noexcept 
 C++11template< class... Args >
explicit value_ptr( in_place_type_t(T), Args&&... args )
 
 C++11template< 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++11value_ptr( cloner_type && cloner ) noexcept 
  value_ptr( deleter_type const & deleter ) 
 C++11value_ptr( deleter_type && deleter ) noexcept 
 C++11template< class V, class ClonerOrDeleter >
value_ptr( V && value, ClonerOrDeleter && cloner_or_deleter )
 
 <C++11template< class V, class ClonerOrDeleter >
value_ptr( V const & value, ClonerOrDeleter const & cloner_or_deleter )
 
 C++11template< class V, class C, class D >
value_ptr( V && value, C && cloner, D && deleter )
 
 <C++11template< class V, class C, class D >
value_ptr( V const & value, C const & cloner, D const & deleter )
 
DestructionC++11~value_ptr() 
AssignmentC++11value_ptr & operator=( std::nullptr_t ) noexcept 
  value_ptr & operator=( T const & value ) 
 C++11template< class U, ... >
value_ptr & operator=( U && value )
 
  value_ptr & operator=( value_ptr const & rhs ) 
 C++11value_ptr & operator=( value_ptr && rhs ) noexcept 
EmplaceC++11template< class... Args >
void emplace( Args&&... args )
 
 C++11template< 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++11explicit operator bool() const noexcept 
 <C++11operator safe_bool() const noexcept 
  bool has_value() const nsvp_noexcept 
  element_type const & value() const 
  element_type & value() 
 C++11template< class U >
constexpr element_type value_or( U && v ) const
 
 <C++11template< 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]stdFunction
Relational operators template< ... >
bool operator op( value_ptr<...> const & lhs, value_ptr<...> const & rhs )
 C++11template< ... >
bool operator op( value_ptr<...> const & lhs, std::nullptr_t )
 C++11template< ... >
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++11template< class T, class C, class D >
value_ptr<T,C,D> make_value( T const & v )
 C++11template< class T >
value_ptr< typename std::decay<T>::type > make_value( T && v )
 C++11template< class T, class...Args >
value_ptr<T,C,D> make_value( Args&&... args )
 C++11template< class T, class U, class... Args >
value_ptr<T,C,D> make_value( std::initializer_list<U> il, Args&&... args )
HashC++11template< 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.

OSCompilerVersions
WindowsClang/LLVM?
 GCC5.2.0, 6.3.0
 Visual C++
(Visual Studio)
8 (2005), 10 (2010), 11 (2012),
12 (2013), 14 (2015, 2017)
GNU/LinuxClang/LLVM3.1.0 - 4.0.0 (Wandbox)
 GCC4.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.
[3] p0201 - A polymorphic value-type for C++. March 2019.
[4] p1950 - indirect_value: A Free-Store-Allocated Value Type For C++. October 2022.

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)