indirect lite – An indirect value-type for C++11 and later in a single-file header-only library (p1950, p3019)
Contents
- Example usage
- In a nutshell
- License
- Dependencies
- Installation
- Synopsis
- Presentations
- Other implementations of indirect
- Notes and references
- Appendix
#include "nonstd/indirect.hpp"
#include <array>
using stdarr = std::array< int, 10 >;
using Vector = nonstd::indirect< stdarr >;
int main()
{
Vector src = nonstd::make_indirect<stdarr>( stdarr( {0, 1, 2, 3, 4, 5, 6, 42} ) );
Vector dst = src;
return (*dst)[7]; // or:dst.value()[7]
}$ g++ -std=c++17 -Wall -I../include/ -o 01-basic.exe 01-basic.cpp & 01-basic.exe
$ echo $?
42
indirect lite is a single-file header-only library to provide indirect type proposed for C++23 for use with C++11 and later. If and when available, the standard library is used, unless configured otherwise.
Features and properties of indirect lite are ease of installation (single header), freedom of dependencies other than the standard library. indirect lite shares the approach to in-place tags with any-lite, expected-lite, optional-lite and with variant-lite and these libraries can be used together.
Limitations of indirect lite are ... [to be summed up].
indirect lite is distributed under the Boost Software License. It contains portions of the reference implementation by the The Indirect Value Authors, which has MIT copyright.
indirect lite has no other dependencies than the C++ standard library.
indirect lite is a single-file header-only library. Put indirect.hpp in the include folder directly into the project source tree or somewhere reachable from your project.
[Envisioned] Depending on the compiler and C++ standard used, indirect lite behaves less or more like the standard's version. To get an idea of the capabilities of indirect lite with your configuration, look at the output of the tests, issuing indirect-main.t --pass @.
There's no standard documentation available yet at cppreference for class indirect, which is proposed to be part of the C++ dynamic memory management library.
| Purpose | Type / value | Notes |
|---|---|---|
| Indirect value type | class indirect | |
| Error reporting | class bad_indirect_access | (extension) |
| Hash | class std::hash | specialisation (extension) |
| In-place construction | struct in_place_tag | |
| in_place | select type or index for in-place construction | |
| in_place_type | select type for in-place construction | |
| (variant) | in_place_index | select index for in-place construction |
| in_place_t | type or index for in-place construction | |
| in_place_type_t | type for in-place construction | |
| (variant) | in_place_index_t | index for in-place construction |
| nonstd_lite_in_place( T) | macro for alias template in_place | |
| nonstd_lite_in_place_type( T) | macro for alias template in_place_type<T> | |
| (variant) | nonstd_lite_in_place_index( T ) | macro for alias template in_place_index<T> |
| nonstd_lite_in_place_t( T) | macro for alias template in_place_t | |
| nonstd_lite_in_place_type_t( T) | macro for alias template in_place_type_t<T> | |
| (variant) | nonstd_lite_in_place_index_t( T ) | macro for alias template in_place_index_t<T> |
| Kind | Std | Method | Result |
|---|---|---|---|
| Types | value_type | T template type | |
| copier_type | C template type (extension) | ||
| deleter_type | D template type (extension) | ||
| Construction | constexpr indirect() noexcept | default-construct | |
| constexpr explicit indirect(T * p, C c=C{}, D d=D{}) | construct, own given pointer | ||
| constexpr indirect(indirect const & other) | copy-construct from other | ||
| constexpr indirect(indirect && other) noexcept | move-construct from other | ||
| template<class ...T> constexpr indirect(nonstd_lite_in_place_t(T), Ts &&... ts) |
in-place construct | ||
| constexpr ~indirect() | destroy current object | ||
| Assignment |
constexpr indirect & operator=(indirect const & rhs) |
copy-assign from other | |
| constexpr indirect & operator=(indirect && rhs) noexcept |
move-assign from other | ||
| Modifiers | constexpr void swap(indirect & other) noexcept(...) | exchange objects | |
| Observers | constexpr T& operator*() & | owned object | |
| constexpr T const & operator*() const & | owned object | ||
| constexpr T && operator*() && noexcept | owned object | ||
| constexpr T const && operator*() const && noexcept | owned object | ||
| constexpr T * operator->() noexcept | owned object | ||
| constexpr T const * operator->() const noexcept | owned object | ||
| constexpr explicit operator bool() const noexcept | engaged | ||
| constexpr bool has_value() const noexcept | engaged (extension) | ||
| constexpr T & value() & | may throw (extension) | ||
| constexpr T const & value() const & | may throw (extension) | ||
| constexpr T && value() && | may throw (extension) | ||
| constexpr T const && value() const && | may throw (extension) | ||
| constexpr copier_type & get_copier() noexcept | (extension) | ||
| constexpr copier_type const & get_copier() const noexcept | (extension) | ||
| constexpr deleter_type & get_deleter() noexcept | (extension) | ||
| constexpr deleter_type const & get_deleter() const noexcept | (extension) |
| Kind | Std | Function | Result |
|---|---|---|---|
| Create |
template<...> constexpr indirect make_indirect(Ts&&... ts) |
in-place construct |
|
| template<...> constexpr indirect allocate_indirect(std::allocator_arg_t, A & a, Ts &&... ts) |
in-place construct |
||
| Swap | void swap(indirect & lhs, indirect & rhs) | exchange contents | |
| Relational operators |
template<...> constexpr bool operatorX(indirect & lhs, indirect & rhs) |
(extension) | |
| template<...> constexpr bool operatorX(indirect & lhs, std::nullptr_t) |
(extension) | ||
| template<...> constexpr bool operatorX(std::nullptr_t, indirect & rhs) |
(extension) | ||
| Three-way operators | C++20 |
template<...> constexpr bool operator**<=>**(...) |
(extension) |
If the compiler supports __has_include(), indirect lite supports the tweak header mechanism. Provide your tweak header as nonstd/indirect.tweak.hpp in a folder in the include-search-path. In the tweak header, provide definitions as documented below, like #define indirect_CPLUSPLUS 201103L.
The C++ standard does not yet provide type std::indirect.
-Dindirect_CPLUSPLUS=201103L
Define this macro to override the auto-detection of the supported C++ standard, if your compiler does not set the __cplusplus macro correctly.
-Dnsiv_CONFIG_NO_EXTENSIONS=0
Define this to 1 if you want to compile without extensions with respect to p1950r2 of October 2022. See below. Default is undefined, and all extensions are enabled.
-Dnsiv_CONFIG_NO_EXTENSION_REF_QUALIFIED_OPERATORS=0
Define this to 1 if you want to compile without this extension. Default is undefined (extension enabled).
-Dnsiv_CONFIG_NO_EXTENSION_VALUE_MEMBERS=0
Define this to 1 if you want to compile without this extension. Default is undefined (extension enabled).
-Dnsiv_CONFIG_NO_EXTENSION_GET_CPY_DEL_MEMBERS=0
Define this to 1 if you want to compile without this extension. Default is undefined (extension enabled).
-Dnsiv_CONFIG_NO_EXTENSION_RELATIONAL_OPERATORS=0
Define this to 1 if you want to compile without this extension. Default is undefined (extension enabled).
-Dnsiv_CONFIG_NO_EXTENSION_STD_HASH=0
Define this to 1 if you want to compile without this extension. Default is undefined (extension enabled).
Jonathan Coe. Vocabulary Types for Composite Class Design. C++ on Sea 2022.
J.B. Coe. Reference implementation at value_types. Value types for composite class design. GitHub.
A previous version is archived at indirect_value.
W. Brown. n3339: A Preliminary Proposal for a Deep-Copying Smart Pointer, Walter E. Brown, 2012.
J.B. Coe. p0201: polymorphic_value: A Polymorphic Value Type for C++, 2022.
J.B. Coe. p1950: indirect_value: A Free-Store-Allocated Value Type For C++, 2022.
J.B. Coe. p3019: indirect and polymorphic: Vocabulary Types for Composite Class Design, 2025. P3019r14 was accepted in the Hagenburg meeting in 2025 for inclusion in C++26.
J. Coplien. Advanced C++ Programming Styles and Idioms (Addison-Wesley), James O. Coplien. 1992.
C. Ericson. Memory Optimization, Christer Ericson, Games Developers Conference (PPT). 2003.
R. Grimm. Visiting a std::variant with the Overload Pattern. 2021.
H. Hinnant. “Incomplete types and shared_ptr / unique_ptr”. 2011.
M. Knejp. p0316: allocate_unique and allocator_delete.
H. Sutter. "Pimpls - Beauty Marks You Can Depend On", Herb Sutter. 1998.
S. Meyers. Effective Modern C++, Item 22: When using the Pimpl Idiom, define special member functions in the implementation file, Scott Meyers. 2014.
A. Upadyshev. PIMPL, Rule of Zero and Scott Meyers, Andrey Upadyshev. 2015.
The version of indirect 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].
click to expand
indirect: Allows to default construct (empty)
indirect: Allows to construct from pointer
indirect: Allows to in-place construct from arguments
indirect: Allows to copy-construct
indirect: Allows to move-construct
indirect: Allows to copy-assign
indirect: Allows to move-assign
indirect: Allows to swap (value)
indirect: Allows to swap (copier)
indirect: Allows to swap (deleter)
indirect: Allows to obtain value, operator->()
indirect: Allows to obtain value, operator->() const
indirect: Allows to obtain value, operator*() &
indirect: Allows to obtain value, operator*() const &
indirect: Allows to obtain value, operator*() &&
indirect: Allows to obtain value,operator*() const &&
indirect: Allows to check if engaged, operator bool()
indirect: Allows to check if engaged, has_value() [extension]
indirect: Allows to obtain value, value() & [extension]
indirect: Allows to obtain value, value() const & [extension]
indirect: Allows to obtain value, value() && [extension]
indirect: Allows to obtain value, value() const && [extension]
indirect: No throw of exception on valid value access, value() & [extension]
indirect: No throw of exception on valid value access, value() const & [extension]
indirect: No throw of exception on valid value access, value() && [extension]
indirect: No throw of exception on valid value access, value() const && [extension]
indirect: Throws on bad value access, value() & [extension]
indirect: Throws on bad value access, value() const & [extension]
indirect: Throws on bad value access, value() && [extension]
indirect: Throws on bad value access, value() const && [extension]
indirect: Allows to obtain copier, get_copier() & [extension]
indirect: Allows to obtain copier, get_copier() const & [extension]
indirect: Allows to obtain deleter, get_deleter() & [extension]
indirect: Allows to obtain deleter, get_deleter() const & [extension]
indirect: Ensure using minimum space requirements
indirect: Ensure noexcept of observers
indirect: Ensure ref- and const-qualifier of observers
indirect: Ensure properties of bad_indirect_access [extension]
indirect: Ensure stats of copy and delete type
indirect: Ensure protection against reentrancy
indirect: Ensure protection against self-assign
indirect: Ensure using source copier when copying
indirect: Ensure working with an incomplete type
make_indirect(): Allows to in-place construct an indirect value from parameters
allocate_indirect(): Allows to in-place construct an indirect value from parameters, with given allocator
swap(): Allows to swap
relational operators: Allows to compare indirect-s [extension]
relational operators: Allows to compare indirect with nullptr [extension]
relational operators: Allows to compare indirect with value convertible to its value_type [extension]
relational operators: Allows to 3-way compare indirect-s [extension]
relational operators: Allows to 3-way compare indirect with nullptr [extension]
relational operators: Allows to 3-way compare indirect with value convertible to its value_type [extension]
std::hash: Allows to hash an indirect [extension]
tweak header: reads tweak header if supported [tweak]