Class Subspace :: sus :: tuple_type :: Tuple
A Tuple is a finite sequence of one or more heterogeneous values.
The Tuple is similar to std::tuple with some differences:
- It allows storing reference types.
- It interacts with iterators through satisfying
Extend
, allowing an iterator tounzip()
into a Tuple of collections that satisfy Extend. - It provides explicit methods for const, mutable or rvalue access to its values.
- It satisfies
Clone
if its elements all satisfyClone
.
Tuple elements can also be accessed through get()
for code that wants to
work generically over tuple-like objects including sus::Tuple
and
std::tuple
.
Tail padding
The Tuple's tail padding may be reused when the Tuple is marked as
[[no_unique_address]]
. The Tuple will have tail padding if the first
type has a size that is not a multiple of the Tuple's alignment. For
example if it's smaller than the alignment, such as Tuple<u8, u64>
which
has (alignof(u64) == sizeof(u64)) - sizeof(u8)
or 7 bytes of tail padding.
struct S {
[[no_unique_address]] Tuple<u32, u64> tuple; // 16 bytes.
u32 val; // 4 bytes.
}; // 16 bytes, since `val` is stored inside `tuple`.
However note that this behaviour is compiler-dependent, and MSVC does not
use the [[no_unique_address]]
hint.
Use sus::data_size_of<T>()
to determine the size of T excluding its tail
padding (so sus::size_of<T>() - sus::data_size_of<T>()
is the tail
padding), which can be useful to ensure you have the expected behaviour from
your types.
Additionally types within the tuple may be placed inside the tail padding of other types in the tuple, should such padding exist.
Generally, but not always, use of tail padding in Tuple is optimized by ordering types (left-to-right in the template variables) from smallest-to- largest for simple types such as integers (which have no tail padding themselves), or in least-to-most tail-padding for more complex types. Elements in a Tuple are stored internally in reverse of the order they are specified, which is why the size of the first element matters for the Tuple's externally usable tail padding.
Static Methods
Construct a Tuple with the default value for the types it contains.
The Tuple's contained types must all be #Default, and will be constructed through that trait.
Construct a Tuple with the given values.
Const References
For Result<const T&, E>
it is possible to bind to a temporary which
would create a memory safety bug. The [[clang::lifetimebound]]
attribute
is used to prevent this via Clang. But additionally, the incoming type is
required to match with sus::construct::SafelyConstructibleFromReference
to prevent conversions that would construct a temporary.
To force accepting a const reference anyway in cases where a type can
convert to a reference without constructing a temporary, use an unsafe
static_cast<const T&>()
at the callsite (and document it =)).
(std::convertible_to<const U&, T> && ... &&
std::convertible_to<const Us&, Ts>)
sizeof...(Ts) == sizeof...(Us)
(::sus::construct::SafelyConstructibleFromReference<T, const U&> &&
... &&
::sus::construct::SafelyConstructibleFromReference<Ts, const Us&>)
(std::convertible_to<U &&, T> && ... &&
std::convertible_to<Us &&, Ts>)
sizeof...(Ts) == sizeof...(Us)
(::sus::construct::SafelyConstructibleFromReference<T, U &&> &&
... &&
::sus::construct::SafelyConstructibleFromReference<Ts, Us &&>)
Converts from Tuple<X', Y', Z'>
to Tuple<X, Y, Z>
when X'
, Y'
,
and Z'
can be converted to X
, Y
, and Z
.
Methods
Gets a const reference to the I
th element in the tuple.
Gets a mutable reference to the I
th element in the tuple.
sus::mem::Clone trait.
sizeof...(Us) == sizeof...(Ts)
(::sus::iter::Extend<T, U> && ... && ::sus::iter::Extend<Ts, Us>)
sus::mem::IsMoveRef<decltype(ii)>
Satisfies sus::iter::Extend for a Tuple of collections that each satisfies Extend for its position-relative type in the iterator of tuples.
The tuple this is called on is a set of collections. The iterable passed in as an argument yields tuples of items that will be appended to the collections.
The item types in the argument can not be deduced, so they must be explicitly specified by the caller, such as:
collections.extend<i32, std::string>(iter_over_tuples_i32_string());
Allows to extend
a tuple of collections that also implement Extend
.
See also: IteratorBase::unzip
.
Removes the I
th element from the tuple, leaving the Tuple in a
moved-from state where it should no longer be used.
Operators
(::sus::cmp::StrongOrd<T> && ... && ::sus::cmp::StrongOrd<Ts>)
sizeof...(Us) == sizeof...(Ts)
(::sus::cmp::StrongOrd<T, U> && ... &&
::sus::cmp::StrongOrd<Ts, Us>)
!(::sus::cmp::StrongOrd<T> && ... && ::sus::cmp::StrongOrd<Ts>)
(::sus::cmp::Ord<T> && ... && ::sus::cmp::Ord<Ts>)
sizeof...(Us) == sizeof...(Ts)
!(::sus::cmp::StrongOrd<T, U> && ... &&
::sus::cmp::StrongOrd<Ts, Us>)
(::sus::cmp::Ord<T, U> && ... && ::sus::cmp::Ord<Ts, Us>)
!(::sus::cmp::Ord<T> && ... && ::sus::cmp::Ord<Ts>)
(::sus::cmp::PartialOrd<T> && ... && ::sus::cmp::PartialOrd<Ts>)
sizeof...(Us) == sizeof...(Ts)
!(::sus::cmp::Ord<T, U> && ... && ::sus::cmp::Ord<Ts, Us>)
(::sus::cmp::PartialOrd<T, U> && ... &&
::sus::cmp::PartialOrd<Ts, Us>)
Compares two Tuples.
Satisfies sus::cmp::StrongOrd<Tuple<...>> if sus::cmp::StrongOrd<...>. Satisfies sus::cmp::Ord<Tuple<...>> if sus::cmp::Ord<...>. Satisfies sus::cmp::PartialOrd<Tuple<...>> if sus::cmp::PartialOrd<...>.
The non-template overloads allow tuple() marker types to convert to Tuple for comparison.
(::sus::cmp::Eq<T> && ... && ::sus::cmp::Eq<Ts>)
sizeof...(Us) == sizeof...(Ts)
(::sus::cmp::Eq<T, U> && ... && ::sus::cmp::Eq<Ts, Us>)
Satisfies the Eq
concept if the types inside satisfy
Eq
.
Implementation Note
The non-template overload allows tuple() marker types to convert to Tuple for comparison.