nils is a C++23 module library that provides a terse and efficient generic implementation of non-zero objects.
The main functionality of the library is concentrated within nils::non_zero.
non_zero does not contain a zero value at any point of forming a reference to its contained value, unless specified otherwise.
Note that there is no restriction on it containing a zero value in between the reads; it is only restricted to contain it if we attempt to read it - which is similar to pointers, which may be null all they want, but you cannot dereference a null pointer.
The contained value is checked for being zero by assertions in debug builds; in release builds this case is optimized for and therefore causes undefined behavior.
Say we want to calculate the reciprocal of a number. Imagine that the user is held at gunpoint and thus cannot enter 0.
import nils;
import std;
using nils::non_zero;
auto reciprocal(non_zero<float> x) -> float
{
// If `x` is zero here, it either triggers an assertion
// or causes undefined behavior (not because of
// division by zero).
return 1.0f / x;
}
auto main() -> int
{
// `non_zero` can be default-initialized, resulting in
// its contained value to be zero. Here be dragons!
non_zero<float> x;
// Remember the user can't enter `0` because whatever.
// Here, we call `get_unchecked` because calling `get`
// would force the value to be checked to be non-zero,
// causing an assertion on debug builds and undefined
// behavior on release builds.
std::cin >> x.get_unchecked();
// Do the thing at last.
std::cout << reciprocal(x);
}It is possible to use non_zero with pointers as it has overloaded operator* and operator->, which also perform zero checks.
Consider an implementation of swapping values under pointers:
import nils;
using nils::non_zero;
template <typename T, typename U>
auto ptr_swap(non_zero<T*> lhs, non_zero<U*> rhs) -> void
{
using std::swap;
// If either of the pointers is null, an assertion is
// triggered in debug builds and undefined behavior is
// invoked in release builds.
swap(*lhs, *rhs);
}The following requirements must be met to use the library:
- C++23 support;
- CMake 3.31.6.
Please note that import std support is experimental in CMake at the time of publishing the library.
If you employ a different version of CMake, then you might need to update the value of CMAKE_EXPERIMENTAL_CXX_IMPORT_STD. Consult the CMake documentation for details.
The library is licensed under the MIT License.
Artemy Astakhov (contact at aeverless dot dev)