On Tue, Jun 7, 2022 at 9:55 AM Phil Endecott via Std-Proposals <std-proposals@lists.isocpp.org> wrote:

Today I have been frustrated by std::tuple not being an aggregate.
I have some non-moveable types and it is difficult to use them
with tuples. That's in contrast to std::pair, which I can use
with piecewise_construct [...]

  std::pair<NonMoveable,NonMoveable> p{ std::piecewise_construct,
                                        std::make_tuple(1,2),
                                        std::make_tuple(3,4) };

  std::tuple<NonMoveable,NonMoveable> t .....????.....

So, what can we do to make std::tuple more like a struct?
One obvious "fix" would be to add std::piecewise_construct support
to std::tuple.

Yes. And I think this is a good idea; I would be willing to help write a proposal for it, unless someone else knows a good reason that a previous attempt failed. (It seems unlikely that this idea has never occurred to anyone before now!)

Why is std::pair piecewise-constructible, but std::tuple didn't need to be? Apparently the reason is that std::pair is std::map::value_type, so in order to make uses-allocator construction work, std::pair needed a way to forward arguments to both of its pieces individually.  std::tuple is never used in that special way as a value_type, so it didn't need piecewise construction.
https://stackoverflow.com/questions/11846634/why-is-there-no-piecewise-tuple-construction

As the SO comments correctly point out: There is no way to make a type be piecewise-constructible and an aggregate at the same time. Piecewise-constructibility requires that you have that specific constructor, and aggregateness requires that you have no constructors. (Tuple has many, many constructors already, so it will never ever be an aggregate. You can give up on that possibility.)


template <typename... TYPES>
struct tuple {
  TYPES fields;...
};

I note that we can use pack expansion with ",". Why not also with ";" ?

Because grammar. `...` goes inside an expression or expression-like-thingie, at the point where you want the expansion to take place. Semicolons by definition separate those thingies. However, this isn't a problem for what you want to do, because the actual syntax for what you want to do would be

    template<class... Ts>
    struct AggregatePseudoTuple {
        Ts... fields;
    };

AIUI, the next problem you'd have to overcome (and the reason this isn't in the language quite yet) is figuring out how to name one of those fields. Barry Revzin has proposed at least one syntax for indexing-into-a-tuple, so maybe one day you'd be able to say something like

    template<size_t K, class... Ts>
    decltype(auto) get(AggregatePseudoTuple<Ts...>& t) {
        return t.fields...[K];  // P1858r2's syntax, if I understand correctly
    }

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1858r2.html (Barry Revzin)

Barry's copious review-of-literature at the end of P1825 includes these earlier papers:
- https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4235.htm (Daveed Vandevoorde)
- https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0535r0.html (Matthew Woehlke)

–Arthur