Modeling complex algebraic structuressuch as multi field products or multi alternative disjoint sumsrequires specialized payload types provides two core vocabulary types pack all fields are present A stores multiple fields and supports the standard C tuple protocol structured bindings and an mechanism Unlike standard tuples packs are strictly flat a cannot be an element of another Appending a splices its fields into the outer pack rather than nesting it To explicitly lift values into a which is useful when conjoining scalars with other packs or copacks use When called without template parameters is deduction only and preserves the value category of its arguments yields whereas calling on an lvalue yields a reference rather than a copy Spelling the template parameters instead e g takes deduction out of the picture each argument is passed as the type you named enabling implicit conversions to happen at the call boundary A reference element becomes something you ask for explicitly yields Note that partial template spelling is not supported all element types must be spelled out explicitly if template parameters are specified copack one exact alternative is present As a payload a models a discriminated union of types Evaluating a via passes the active alternative to the callback Because is self flattening nested s do not occur A selected alternative that is itself tuple likesuch as or is unpacked one level passing its immediate constituents as separate arguments Since normalized shapes are sums of products one level of unpacking is sufficient to supply the product s fields as function arguments To explicitly lift a single scalar value into a single alternative coproduct use Unlike it always decays a alternative can never be a reference When a contains exactly one alternative it is singular and supports direct value extraction via the utility resolvable via ADL which propagates references with the same semantics as A can be lifted into a including packs holding references but a cannot contain a There is algebraic equivalence between a hypothetical containing a which is disallowed and a specific shape of containing a see Product composition with operator& conjunction for details A key safety guarantee of is exhaustive matching Operations that evaluate a such as and delegate to a multidispatch implementation that enforces compile time exhaustiveness If the callback or overload set fails to handle any possible alternative in the the compilation is ill formed Direct extraction is disallowed for multi alternative types because the active alternative is a run time property meaning a multi alternative has no single static return type Extraction must go through dispatch which is exhaustive libfn pack get tuple_size tuple_element append libfn pack pack pack pack fn as_pack as_pack as_pack 42 pack<int> as_pack x x pack<int&> as_pack<bool int> x d as_pack<int const&> x pack<int const&> auto test_pack int x 12 double d 3 14 > void fn pack p UserId User CTAD maybe_unused auto id user p Structured bindings work naturally Ordered non deduplicated fields using P fn pack<UserId User User> static_assert std tuple_size_v<P> 3 Found via ADL like std get using std get static_assert std same_as<decltype get<0> p UserId &> Splicing scalars or other packs via append auto row fn pack UserId append FilePath auto wider std move row append fn pack true 3 static_assert std same_as<decltype wider fn pack<UserId FilePath bool int>> Explicitly lifting a single scalar value into a pack auto lifted_lvalue fn as_pack x static_assert std same_as<decltype lifted_lvalue fn pack<int &>> auto lifted_rvalue fn as_pack 42 static_assert std same_as<decltype lifted_rvalue fn pack<int>> Spelling the element type explicitly can be used to opt out of reference preservation auto copied fn as_pack<int> x static_assert std same_as<decltype copied fn pack<int>> or to force a specific reference type subject to parameter binding rules auto referenced fn as_pack<int const &> x static_assert std same_as<decltype referenced fn pack<int const &>> The explicit form also coerces the argument converts at the call boundary auto coerced fn as_pack<bool int> x d static_assert std same_as<decltype coerced fn pack<bool int>> copack copack apply copack copack pack std tuple std array fn as_copack value as_pack copack copack get apply pack copack pack copack pack copack copack pack struct IntegerToken struct StringToken auto test_copack > void static constexpr fn copack_for<IntegerToken StringToken> token IntegerToken Member apply eliminates the copack by routing the active alternative to an overload set static constexpr auto value token apply fn overload IntegerToken return 1 StringToken return 2 static_assert value 1 Storing a pack inside a copack is allowed including a pack holding a reference auto cpr fn as_copack fn as_pack<int const &> value static_assert std same_as<decltype cpr fn copack<fn pack<int const &>>> Singular lift and direct value extraction only allowed for singular copacks auto cp fn as_copack 42 using std get static_assert std same_as<decltype get cp int &> copack copack transform apply copack get copack get