On Tue, Apr 1, 2025 at 7:46 AM Yexuan Xiao via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
P1061 introduced packs in structured binding declarations, an excellent improvement that allows tuple-like types to be converted into packs while bundling remaining elements.

auto [x, ...rest, z] = std::tuple<int,int,int>{0,1,2};
auto t = std::forward_as_tuple(rest...);

However, pack expansions cannot directly initialize structured bindings:

auto [x, ...rest, z] = args...; // currently unsupported and always ill-formed

That's correct. The idea of a structured binding is that you have one thing on the left, one thing on the right, and you're giving names (binding names) to the pieces of the left-hand thing.
So for example we would expect this to work—
    template<class... Ts>
    void f(Ts... ts) {
      auto obj = ts...;
    }
    int main() { f(42); }
—because `ts...` expands to `42`, and `auto obj = 42;` is OK. The only reason it doesn't work today is a quirk of the grammar. (There's also a special rule that says a pack-expansion must be sufficiently general: https://eel.is/c++draft/temp#res.general-6.5 forbids templates containing pack-expansions that must contain zero elements. But this doesn't hit that rule because this pack-expansion must contain one element. So I believe the issue here is that the `declaration` grammar doesn't permit an ellipsis in that position.)

Compare this, which does work fine:
    template<class... Ts>
    void f(Ts... ts) {
      auto obj = auto(ts...);
    }
    int main() { f(42); }
Here, the grammar doesn't get in our way, and `auto(42)` gives us the initializer for `int obj`. But again `auto [...xs] = auto(ts...)` doesn't work, because `int obj` is not structured-bindable. (It doesn't have any "elements"; it's just an int.)

We can also write:
    template<class... Ts>
    void f(Ts... ts) {
      auto obj = {ts...};
    }
    int main() { f(42); }
But this doesn't work with `auto [...xs]`, because here we deduce `std::initializer_list<int> obj`, and `initializer_list<int>` is not structured-bindable. (Semantically it doesn't know how many elements it has; and mechanically, the data members it does have — a pair of pointers — are private, not public.)

Now, I agree that in a vacuum it would be nice if we could have
    auto [...xs] = {ts...};
For example,
    auto [x, y] = {42, "hello"};
This doesn't work today because (1) {42, "hello"} has no type, and can't deduce a consistent `T` to put in `initializer_list<T>` either; and (2) `initializer_list` is not structured-bindable. But it does seem relatively obvious that the programmer wants to give the value 42 to `x` and "hello" to `y`, as if by
    auto x = 42;
    auto y = "hello";
The problem is, that's not what a structured binding declaration does. What it's supposed to do is: Create a single object on the left-hand side, and bind names to its pieces. What is the type of that single object here? It can't be std::tuple; that's a library type. It could be an ad-hoc unnamed standard-layout struct type — I think that could work. I wouldn't pursue that myself, but if you really really wanted this kind of thing, that's the direction I might consider exploring.

my $.02,
Arthur