Class Subspace :: sus :: choice_type :: Choice
A tagged union, or sum type.
A Choice
is always set to one of its Tags
values, and each tag has zero
or more types attached to it as data values.
Choice
can be thought of as a combination of an enum
and a
std::variant
, and
typically the Tags
are specified to be values in an enum
.
A Choice
always has an active member, as the tag must be specified at
construction, and the asociated values for the tag are always set as they
must be set when the tag is specified. This means a Choice
is always in a
fully specified state, or it is moved-from. Once it is moved from it may not
be used except to be re-initialized.
Use the sus_choice_types()
macro to specify the types in a Choice
type.
To access the values in Choice
, the current tag must be specified as a
template parameter, and it will be checked for correctness. When it does not
match, the Choice
method will panic.
as<Tag>()
gives const access to all the values attached to the tag.as_mut<Tag>()
gives mutable access to all the values attached to the tag. It is only callable on mutableChoice
.into_inner<Tag>()
moves all values attached to the tag out of theChoice
and marks theChoice
as moved-from. It is only callable on an rvalueChoice.
get<Tag>()
returns a const reference to the values attached to the tag if its currently active, and returnsNone
if the tag is not active.get_mut<Tag>()
returns a mutable reference to the values attached to the tag if its currently active, and returnsNone
if the tag is not active.
Examples
This Choice
holds either a u64
with
the First
tag or a u32
with the Second
tag.
enum class Order { First, Second };
using EitherOr = Choice<sus_choice_types(
(Order::First, u64),
(Order::Second, u32)
)>;
A Choice
tag may be associated with no values by making its type void
or
may be associated with more than one type in which case all access will be
done with a Tuple
.
enum class Order { First, Second };
using EitherOr = Choice<sus_choice_types(
(Order::First, void),
(Order::Second, std::string, i32)
)>;
auto e1 = EitherOr::with<Order::First>();
auto e2 = EitherOr::with<Order::Second>("text", 123);
The Choice
type can be used in a switch
, with each case being one of its
possible tag values. Within each tag case block, the values can be pulled
out of the Choice
with as
in a
type-safe and memory-safe way.
enum class Order { First, Second };
using EitherOr = Choice<sus_choice_types(
(Order::First, u64),
(Order::Second, std::string, i32)
)>;
auto e = EitherOr::with<Order::Second>("hello worl", 0xd);
switch (e) {
case Order::First: {
const auto& i = e.as<Order::First>();
// We don't get here.
fmt::println("First has u64 {}", i);
break;
}
case Order::Second: {
const auto& [s, i] = e.as<Order::Second>();
// Prints "Second has hello world".
fmt::println("Second has {}{:x}", s, i);
break;
}
}
Choice
will re-export the tag value type as a nested Tag
subtype. This
allows access to the Choice's values though MyChoiceType::Tag::Name
.
enum class Order { First, Second };
using EitherOr = Choice<sus_choice_types(
(Order::First, u64),
(Order::Second, u32)
)>;
auto x = EitherOr::with<EitherOr::Tag::First>(987u);
Static Methods
__private::StorageCount<StorageTypeOfTag<V>> == 1u
sus::construct::SafelyConstructibleFromReference<StorageTypeOfTag<V>, U &&>
std::convertible_to<U &&, StorageTypeOfTag<V>>
__private::StorageCount<StorageTypeOfTag<V>> > 1u
sizeof...(Us) ==
__private::StorageCount<StorageTypeOfTag<V>>
sus::choice_type::__private::StorageIsSafelyConstructibleFromReference<StorageTypeOfTag<V>, Us &&...>
std::constructible_from<StorageTypeOfTag<V>, Us &&...>
Constructs a Choice
with the V
tag indicating its active member, and
with the parameters used to set the associated values.
If the associated type of the tag is void
then with()
takes no
parameters.
Methods
Returns a const reference to the value(s) inside the Choice
.
The function has a template parameter specifying the tag of the active
member in the Choice
.
If the active member's associated type is void
then this method is
deleted and can't be called.
If the active member has a single value, a reference to it is returned
directly, otherwise a Tuple of references is returned to all values in the
active member.
Panics
The function will panic if the active member does not match the tag value passed as the template parameter.
Returns a mutable reference to the value(s) inside the Choice
.
The function has a template parameter specifying the tag of the active
member in the Choice
.
If the active member's associated type is void
then this method is
deleted and can't be called.
If the active member has a single value, a reference to it is returned
directly, otherwise a Tuple of references is returned to all values in the
active member.
Panics
The function will panic if the active member does not match the tag value passed as the template parameter.
Returns a const reference to the value(s) inside the Choice
.
If the template parameter does not match the active member in the
Choice
, the function returns None
.
If the active member's associated type is void
then this method is
deleted and can't be called.
If the active member has a single value, a reference to it is returned
directly, otherwise a Tuple
of references is
returned to all values in the active member.
Returns a mutable reference to the value(s) inside the Choice
.
If the template parameter does not match the active member in the
Choice
, the function returns None
.
If the active member's associated type is void
then this method is
deleted and can't be called.
If the active member has a single value, a reference to it is returned
directly, otherwise a Tuple
of references is
returned to all values in the active member.
__private::StorageCount<StorageTypeOfTag<V>> > 0u
!std::is_reference_v<StorageTypeOfTag<V>>
Returns a const reference to the value(s) inside the Choice
.
The function has a template parameter specifying the tag of the active
member in the Choice
.
If the active member's associated type is void
then this method is
deleted and can't be called.
If the active member has a single value, a reference to it is returned
directly, otherwise a Tuple
of references is
returned to all values in the active member.
Safety
If the active member does not match the tag value passed as the template parameter, Undefined Behaviour results.
__private::StorageCount<StorageTypeOfTag<V>> > 0u
Returns a mutable reference to the value(s) inside the Choice
.
The function has a template parameter specifying the tag of the active
member in the Choice
.
If the active member's associated type is void
then this method is
deleted and can't be called.
If the active member has a single value, a reference to it is returned
directly, otherwise a Tuple
of references is
returned to all values in the active member.
Safety
If the active member does not match the tag value passed as the template parameter, Undefined Behaviour results.
__private::StorageCount<StorageTypeOfTag<V>> > 0u
Unwraps the Choice
to move out the current value(s) inside the Choice
.
The function has a template parameter specifying the tag of the active
member in the Choice
.
If the active member's associated type is void
then this method is
deleted and can't be called.
If the active member has a single value, an rvalue reference to it is
returned directly, otherwise a Tuple
of
rvalue references is returned to all values in the active member.
Panics
The function will panic if the active member does not match the tag value passed as the template parameter.
__private::StorageCount<StorageTypeOfTag<V>> > 1u
sizeof...(Us) ==
__private::StorageCount<StorageTypeOfTag<V>>
sus::choice_type::__private::StorageIsSafelyConstructibleFromReference<StorageTypeOfTag<V>, Us &&...>
std::constructible_from<StorageTypeOfTag<V>, Us &&...>
Changes the Choice
to make the tag V
active, and sets the associated
values of V
from the paramters.
If the associated type of the tag is void
then set()
takes no
parameters.
Returns which is the active member of the Choice
.
Typically to access the data in the Choice
, a switch
statement would
be used, so as to call the getter or setter methods with the right value
specified as a template parameter. When used in a switch
statement, the
which
method can be omitted.
Example
switch (my_choice) {
case Value1: return my_choice.as<Value1>().stuff;
case Value2: return my_choice.as<Value2>().andmore;
case Value3: return my_choice.as<Value3>().stufftoo;
}
Inspiration
████████
████▓▓░░▓▓██
██▓▓▓▓▓▓▓▓██
██▓▓▓▓░░▓▓██
██░░▓▓▓▓▓▓██
██▓▓▓▓▓▓▓▓▓▓██
██▓▓▓▓░░▓▓▓▓██
████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓████████
██▓▓░░▓▓▓▓▓▓░░▓▓▓▓▓▓▓▓▓▓░░▓▓▓▓▓▓██
██████████████████▓▓██████████████
██ ██ ██
██ ██ ██ ██
██ ██ ████ ██
██ ██ ██
██▒▒ ██ ██
██▒▒ ██ ██
████████████████████
██ ██
██ ██▓▓██
▓▓ ██▓▓▓▓██
██ ████░░▓▓▓▓██ ▓▓▓▓▓▓▓▓▓▓▓▓
██ ██ ██▓▓▓▓░░▓▓██ ▓▓░░░░░░░░░░░░
██ ██ ████▓▓▓▓▓▓██ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓ ██ ██ ██▓▓▓▓▓▓░░▓▓██ ▓▓▓▓░░░░░░░░░░░░
▓▓▓▓▓▓▓▓▓▓██████▓▓▓▓██▓▓░░▓▓▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
██████████ ▓▓▓▓░░░░░░░░░░░░
██ ██ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓
██ ██ ▓▓░░░░░░░░░░░░
██ ██ ▓▓▓▓▓▓▓▓▓▓▒▒
████
Conversions
Support for using Choice in a switch()
statment.
See the type's top level documentation for an example.