<xstd/bits/bit_set/indeterminate.hpp>¶
xstd::indeterminate_t, xstd::indeterminate, xstd::indeterminate_array, XSTD_INDETERMINATE¶
#define XSTD_INDETERMINATE see below
struct indeterminate_t { explicit indeterminate_t() = default; };
inline constexpr indeterminate_t indeterminate{};
template<class T, size_t K>
requires constructible_from<T, indeterminate_t>
constexpr auto indeterminate_array() noexcept(is_nothrow_constructible_v<T, indeterminate_t>) -> array<T, K>;
A tag that asks an owner to leave its blocks default-initialized, the first step of a two-step initialization:
auto s = bit_fixed_set<64>(indeterminate); writes nothing, and s = t; then gives it a value. It is for a set built
in a hot path and assigned before anything reads it, such as a field of a struct that a later step fills. The fixed
arrays take it too: bit_array<N>(indeterminate) and bit_fixed_valarray<N>(indeterminate). Its default
constructor is explicit, so {} cannot stand in for it.
indeterminate_array<T, K>() returns an array<T, K> whose every element is built from the tag. Each element is
initialized directly from the prvalue T(indeterminate), so nothing is copied or zeroed. It fills an array member
in a default member initializer, as a braced {indeterminate} fills only the first element.
Notes¶
- The owners of a fixed width take the tag:
basic_bit_fixed_setand the sets that name it,bit_enum_setandbit_flag_set,basic_bit_arrayandbasic_bit_fixed_valarray. A run-time width starts at zero and has nothing to leave unwritten. Until it is assigned, the owner's only valid operations are assignment and destruction: reading it in any other way,size(),contains, a subscript, a comparison, a copy, is undefined. A hardened build cannot check this; MemorySanitizer can. - Only a whole write may follow, so the tag writes nothing at any width, the bits past
Nof a width that does not fill its blocks included: the assignment that follows copies them clear from an owner that has a value. - Inserting a key after the tag,
a[0] = true, or any other write of one bit, is undefined: a bit is written by reading the block that holds it, and that block has no value yet. - A default-constructed set is empty, as [container.reqmts] has
X u;, and a default-constructed array is every positionfalse, value-initialized or not: the tag is the only way to an indeterminate owner.array<bool, N> a; a[0] = true;is valid, and the packeda[0] = truereads the block that bit 1 shares, so a default-constructedbit_arraystarts clear to admit the same code. - Under C++26, P2795R5 gives an automatic variable's storage erroneous values, which an
implementation may fill in whatever its constructors leave. A variable that must stay unwritten says so with
[[indeterminate]], which applies to the whole variable.XSTD_INDETERMINATEis that attribute's name where the language and the compiler have it, and empty elsewhere, so[[XSTD_INDETERMINATE]] auto s = bit_fixed_set<64>(indeterminate);compiles under C++23 as under C++26, as[[XSTD_NO_UNIQUE_ADDRESS]]does. A definition of it made before the header is included wins.
See also¶
| Entity | Relation |
|---|---|
basic_bit_fixed_set |
an owner that takes the tag, and empty by default |
basic_bit_array |
an owner that takes the tag, and zeroed by default, so that writing one element after default construction is valid, as for array<bool, N> |
basic_bit_fixed_valarray |
an owner that takes the tag, and zeroed by default, as basic_bit_array is |
boost::container::default_init_t |
Boost.Container's tag for default- rather than value-initialized elements |
make_unique_for_overwrite |
the standard's default-initializing counterpart of make_unique, from P1020R1 |