Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/martinmoene/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
https://github.com/martinmoene/value-ptr-lite

cpp11 cpp98 header-only no-dependencies single-file smart-pointer

Last synced: 5 days ago
JSON representation

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

Awesome Lists containing this project

README

        

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

**Note**: You may want to consider using [*indirect\_value lite (p1950)*](https://github.com/martinmoene/indirect-value-lite) instead of *value\_ptr lite*.

[![Language](https://img.shields.io/badge/C%2B%2B-98/11/14/17-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) [![License](https://img.shields.io/badge/license-BSL-blue.svg)](https://opensource.org/licenses/BSL-1.0) [![Build Status](https://github.com/martinmoene/value-ptr-lite/actions/workflows/ci.yml/badge.svg)](https://github.com/martinmoene/value-ptr-lite/actions/workflows/ci.yml) [![Build status](https://ci.appveyor.com/api/projects/status/w2dgn3fxyrd6vcq8?svg=true)](https://ci.appveyor.com/project/martinmoene/value-ptr-lite) [![Version](https://badge.fury.io/gh/martinmoene%2Fvalue-ptr-lite.svg)](https://github.com/martinmoene/value-ptr-lite/releases) [![download](https://img.shields.io/badge/latest-download-blue.svg)](https://raw.githubusercontent.com/martinmoene/value-ptr-lite/master/include/nonstd/value_ptr.hpp) [![Conan](https://img.shields.io/badge/on-conan-blue.svg)](https://bintray.com/martinmoene/nonstd-lite/value-ptr-lite%3Anonstd-lite/_latestVersion) [![Vcpkg](https://img.shields.io/badge/on-vcpkg-blue.svg)](https://vcpkg.link/ports/value-ptr-lite) [![Try it on godbolt online](https://img.shields.io/badge/on-godbolt-blue.svg)](https://godbolt.org/z/cjdGue)

**Contents**
- [Example usage](#example-usage)
- [In a nutshell](#in-a-nutshell)
- [Dependencies](#dependencies)
- [Installation](#installation)
- [Synopsis](#synopsis)
- [Reported to work with](#reported-to-work-with)
- [Building tests and examples](#building-tests-and-examples)
- [Other value_ptr implementations](#other-value-ptr-implementations)
- [Notes and references](#notes-and-references)
- [Appendix](#appendix)

Pimpl example usage
-------------------

```Cpp
// 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 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]](#ref1) and on `impl_ptr` by Andrey Upadyshev [[2]](#ref2).

**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](LICENSE.txt).

Dependencies
------------
*value-ptr lite* has no other dependencies than the [C++ standard library](http://en.cppreference.com/w/cpp/header).

Installation
------------
*value-ptr lite* is a single-file header-only library. Put `value_ptr.hpp` in the [include](include) folder directly into the project source tree or somewhere reachable from your project.

Synopsis
--------

**Contents**
- [Types in namespace nonstd](#types-in-namespace-nonstd)
- [Interface of *value-ptr lite*](#interface-of-value-ptr-lite)
- [Non-member functions for *value-ptr lite*](#non-member-functions-for-value-ptr-lite)
- [Configuration macros](#configuration-macros)

### Types in namespace nonstd

| Purpose |[[1]](#ref1) | [[2]](#ref2)| 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]](#ref1) | [[2]](#ref2)|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 ) |  |
|   |– |– |
**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 ) |  |
|   |– |– |
**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 |  |
|   |– |– |
constexpr element_type **value_or**( U && v ) const |  |
|   |– |– |
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]](#ref1)| [[2]](#ref2)| 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 |– |– |
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](https://buckbuild.com/) or [CMake](http://cmake.org) version 2.8.12 or later to be installed and in your PATH.
- A [suitable compiler](#reported-to-work-with).

The [*lest* test framework](https://github.com/martinmoene/lest) is included in the [test folder](test).

The following steps assume that the [*value_ptr lite* source code](https://github.com/martinmoene/value-ptr-lite) 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](#features).

Other value-ptr implementations
-------------------------------
- LoopPerfect. [valuable: A C++ smart-pointer with value-semantics](https://github.com/LoopPerfect/valuable) (C++14).
- Jonathan B. Coe. [indirect_value: An indirect value-type for C++ (perfect-pimpl)](https://github.com/jbcoe/indirect_value).
- [Search _value ptr_ on GitHub](https://github.com/search?l=C%2B%2B&q=value_ptr&type=Repositories).

Notes and references
--------------------

[1] Gaetano Checinski. [value_ptr — The Missing C++ Smart-pointer](https://hackernoon.com/value-ptr-the-missing-c-smart-pointer-1f515664153e) ([GitHub](https://github.com/LoopPerfect/valuable)). May 2017.
[2] Andrey Upadyshev. [PIMPL, Rule of Zero and Scott Meyers](http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html) ([GitHub](https://github.com/oliora/samples/blob/master/spimpl.h)). December 29, 2015.
[3] [p0201 - A polymorphic value-type for C++](https://wg21.link/p0201). March 2019.
[4] [p1950 - indirect_value: A Free-Store-Allocated Value Type For C++](https://wg21.link/p1950). 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)
```