You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fn::pack is an aggregate, so brace initialization can bind a reference element to a temporary: fn::pack<int const &>{42} compiles. For a named local initialized this way, the temporary lives as long as the pack. Returning the pack does not extend the temporary's lifetime, so the returned pack's element dangles.
#include<fn/pack.hpp>template <typename T, typename... Args>
concept brace_constructible = requires(Args &&...args) { T{static_cast<Args &&>(args)...}; };
template <typename T, typename... Args>
concept spelled_lift = requires(Args &&...args) { fn::as_pack<T>(static_cast<Args &&>(args)...); };
// pack's braces bind a reference element to a temporary ...static_assert(brace_constructible<fn::pack<intconst &>, int>);
// ... which the spelled lift refuses, binding only an lvaluestatic_assert(not spelled_lift<intconst &, int>);
static_assert(spelled_lift<intconst &, int &>);
// Compiles; the int dies when make returns, so reading the element of make() is a use-after-return.automake() -> fn::pack<int const &> { return fn::pack<intconst &>{42}; }
intmain() {}
Reading the element of make() is reported by AddressSanitizer as stack-use-after-return (gcc 16, with ASAN_OPTIONS=detect_stack_use_after_return=1).
Other reference APIs reject temporaries, following C++26 optional<T&>, reference alternatives in copack and choice (#451), as_pack with explicit element types, and append(std::in_place_type<T&>, ...). Brace initialization of pack still accepts them.
To reject temporaries, reference elements must be initialized through constructors. pack could gain constructors, or store reference elements behind a constructor that rejects temporaries, as copack does for reference alternatives. Either approach needs to account for aggregate initialization, structured bindings, triviality and constexpr.
This issue also blocks deprecating as_pack. #451 deprecates as_copack and as_choice in favour of naming the type, whose constructors refuse a temporary; the same advice for as_pack would replace as_pack<int const &>(x) with pack<int const &>{x}, which accepts what the lift refuses.
Activity
Deprecate `as_copack` and `as_choice` in favour of naming the type