indirect-value-lite

September 27, 2025 · View on GitHub

indirect_value lite – An indirect value-type for C++11 and later in a single-file header-only library (p1950)

Language License Build Status Version download Try it on godbolt online

Contents

Example usage

#include "nonstd/indirect_value.hpp"
#include <array>

using stdarr = std::array< int, 10 >;
using Vector = nonstd::indirect_value< stdarr >;

int main()
{
    Vector src = nonstd::make_indirect_value<stdarr>( stdarr( {0, 1, 2, 3, 4, 5, 6, 42} ) );

    Vector dst = src;

    return (*dst)[7];  // or:dst.value()[7]
}

Compile and run

$ g++ -std=c++17 -Wall -I../include/ -o 01-basic.exe 01-basic.cpp & 01-basic.exe
$ echo $?
42

In a nutshell

indirect_value lite is a single-file header-only library to provide indirect_value 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_value lite are ease of installation (single header), freedom of dependencies other than the standard library. indirect_value 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_value lite are ... [to be summed up].

License

indirect_value 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.

Dependencies

indirect_value lite has no other dependencies than the C++ standard library.

Installation

indirect_value lite is a single-file header-only library. Put indirect_value.hpp in the include folder directly into the project source tree or somewhere reachable from your project.

Synopsis

Documentation of class indirect_value

[Envisioned] Depending on the compiler and C++ standard used, indirect_value lite behaves less or more like the standard's version. To get an idea of the capabilities of indirect_value lite with your configuration, look at the output of the tests, issuing indirect_value-main.t --pass @.

There's no standard documentation available yet at cppreference for class indirect_value, which is proposed to be part of the C++ dynamic memory management library.

Types and values in namespace nonstd

PurposeType / valueNotes
Indirect value typeclass indirect_value 
Error reportingclass bad_indirect_value_access(extension)
Hashclass std::hashspecialisation (extension)
   
In-place constructionstruct in_place_tag 
 in_placeselect type or index for in-place construction
 in_place_typeselect type for in-place construction
 (variant)in_place_indexselect index for in-place construction
 in_place_ttype or index for in-place construction
 in_place_type_ttype for in-place construction
 (variant)in_place_index_tindex 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>

Interface of indirect_value lite

KindStdMethodResult
Types value_typeT template type
  copier_typeC template type (extension)
  deleter_typeD template type (extension)
Construction constexpr indirect_value() noexceptdefault-construct
  constexpr explicit indirect_value(T * p, C c=C{}, D d=D{})construct, own given pointer
  constexpr indirect_value(indirect_value const & other)copy-construct from other
  constexpr indirect_value(indirect_value && other) noexceptmove-construct from other
  template<class ...T>
constexpr indirect_value(nonstd_lite_in_place_t(T), Ts &&... ts)
in-place construct
  constexpr ~indirect_value()destroy current object
Assignment
 
 constexpr indirect_value &
operator=(indirect_value const & rhs)
copy-assign from other
  constexpr indirect_value &
operator=(indirect_value && rhs) noexcept
move-assign from other
Modifiers constexpr void swap(indirect_value & other) noexcept(...)exchange objects
Observers constexpr T& operator*() &owned object
  constexpr T const & operator*() const &owned object
  constexpr T && operator*() && noexceptowned object
  constexpr T const && operator*() const && noexceptowned object
  constexpr T * operator->() noexceptowned object
  constexpr T const * operator->() const noexceptowned object
  constexpr explicit operator bool() const noexceptengaged
  constexpr bool has_value() const noexceptengaged (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)

Algorithms for indirect_value lite

KindStdFunctionResult
Create
 
 template<...> constexpr indirect_value
make_indirect_value(Ts&&... ts)
in-place construct
 
  template<...> constexpr indirect_value
allocate_indirect_value(std::allocator_arg_t, A & a, Ts &&... ts)
in-place construct
 
Swap void swap(indirect_value & lhs, indirect_value & rhs)exchange contents
Relational operators
 
 template<...> constexpr bool
operatorX(indirect_value & lhs, indirect_value & rhs)
(extension)
  template<...> constexpr bool
operatorX(indirect_value & lhs, std::nullptr_t)
(extension)
  template<...> constexpr bool
operatorX(std::nullptr_t, indirect_value & rhs)
(extension)
Three-way operatorsC++20
 
template<...> constexpr bool
operator**<=>**(...)
(extension)
 

Configuration

Tweak header

If the compiler supports __has_include(), indirect_value lite supports the tweak header mechanism. Provide your tweak header as nonstd/indirect_value.tweak.hpp in a folder in the include-search-path. In the tweak header, provide definitions as documented below, like #define indirect_value_CPLUSPLUS 201103L.

Select std::indirect_value or nonstd::indirect_value

The C++ standard does not yet provide type std::indirect_value.

Standard selection macro

-Dindirect_value_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.

Disable extensions

-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.

Disable reference qualified operators extension

-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).

Disable value() members extension

-Dnsiv_CONFIG_NO_EXTENSION_VALUE_MEMBERS=0
Define this to 1 if you want to compile without this extension. Default is undefined (extension enabled).

Disable get_copier(), get_deleter() extension

-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).

Disable relational operators extension

-Dnsiv_CONFIG_NO_EXTENSION_RELATIONAL_OPERATORS=0
Define this to 1 if you want to compile without this extension. Default is undefined (extension enabled).

Disable std::hash extension

-Dnsiv_CONFIG_NO_EXTENSION_STD_HASH=0
Define this to 1 if you want to compile without this extension. Default is undefined (extension enabled).

Other implementations of indirect_value

J.B. Coe. Reference implementation: indirect_value. An indirect value-type for C++. GitHub.

Notes and references

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++.
J.B. Coe. p1950: indirect_value: A Free-Store-Allocated Value Type For C++.
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.

Appendix

A.1 Compile-time information

The version of indirect_value 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 indirect_value lite test specification

click to expand

indirect_value: Allows to default construct (empty)
indirect_value: Allows to construct from pointer
indirect_value: Allows to in-place construct from arguments
indirect_value: Allows to copy-construct
indirect_value: Allows to move-construct
indirect_value: Allows to copy-assign
indirect_value: Allows to move-assign
indirect_value: Allows to swap (value)
indirect_value: Allows to swap (copier)
indirect_value: Allows to swap (deleter)
indirect_value: Allows to obtain value, operator->()
indirect_value: Allows to obtain value, operator->() const
indirect_value: Allows to obtain value, operator*() &
indirect_value: Allows to obtain value, operator*() const &
indirect_value: Allows to obtain value, operator*() &&
indirect_value: Allows to obtain value,operator*() const &&
indirect_value: Allows to check if engaged, operator bool()
indirect_value: Allows to check if engaged, has_value() [extension]
indirect_value: Allows to obtain value, value() & [extension]
indirect_value: Allows to obtain value, value() const & [extension]
indirect_value: Allows to obtain value, value() && [extension]
indirect_value: Allows to obtain value, value() const && [extension]
indirect_value: No throw of exception on valid value access, value() & [extension]
indirect_value: No throw of exception on valid value access, value() const & [extension]
indirect_value: No throw of exception on valid value access, value() && [extension]
indirect_value: No throw of exception on valid value access, value() const && [extension]
indirect_value: Throws on bad value access, value() & [extension]
indirect_value: Throws on bad value access, value() const & [extension]
indirect_value: Throws on bad value access, value() && [extension]
indirect_value: Throws on bad value access, value() const && [extension]
indirect_value: Allows to obtain copier, get_copier() & [extension]
indirect_value: Allows to obtain copier, get_copier() const & [extension]
indirect_value: Allows to obtain deleter, get_deleter() & [extension]
indirect_value: Allows to obtain deleter, get_deleter() const & [extension]
indirect_value: Ensure using minimum space requirements
indirect_value: Ensure noexcept of observers
indirect_value: Ensure ref- and const-qualifier of observers
indirect_value: Ensure properties of bad_indirect_value_access [extension]
indirect_value: Ensure stats of copy and delete type
indirect_value: Ensure protection against reentrancy
indirect_value: Ensure protection against self-assign
indirect_value: Ensure using source copier when copying
indirect_value: Ensure working with an incomplete type
make_indirect_value(): Allows to in-place construct an indirect value from parameters
allocate_indirect_value(): Allows to in-place construct an indirect value from parameters, with given allocator
swap(): Allows to swap
relational operators: Allows to compare indirect_value-s [extension]
relational operators: Allows to compare indirect_value with nullptr [extension]
relational operators: Allows to compare indirect_value with value convertible to its value_type [extension]
relational operators: Allows to 3-way compare indirect_value-s [extension]
relational operators: Allows to 3-way compare indirect_value with nullptr [extension]
relational operators: Allows to 3-way compare indirect_value with value convertible to its value_type [extension]
std::hash: Allows to hash an indirect_value [extension]
tweak header: reads tweak header if supported [tweak]