Date: Mon, 07 Jul 2025 12:08:50 +0300
Updated. I did not understand what undesired casts are so I only
forbade dangling references.
On Mon, 2025-07-07 at 01:56 +0000, F. v.S. via Std-Proposals wrote:
>
> construct<T> is roughly equivalent to std::make_from_tuple, except
> that
> - it is (or ought to be) a CPO, and
> - its arguments are not packed.
>
>
> I believe we should impose constraints similar to those of
> std::make_from_tuple to avoid dangling references and undesired
> casts.
>
>
> Thanks,
> F.v.S.
> From: Std-Proposals <std-proposals-bounces_at_[hidden]> on
> behalf of Avi Kivity via Std-Proposals <std-
> proposals_at_[hidden]>
> Sent: Monday, July 7, 2025 4:24
> To: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>; std-
> proposals_at_[hidden] <std-proposals_at_[hidden]>
> Cc: Avi Kivity <avi_at_[hidden]>
> Subject: Re: [std-proposals] std::construct<T>
>
>
> I wrote it up:
>
> https://github.com/avikivity/cpp-std-proposals/blob/std-construct/std-construct.md#proposal-for-stdconstruct-function-object
>
> On Wed, 2025-05-14 at 22:30 +0300, Avi Kivity wrote:
> > You're correct, std::construct should be a variable template with
> > one parameter.
> >
> > Regarding make_obj vs std::construct, obj is not a word, and I
> > think the standard should try hard to use words. I think
> > std::construct is consistent with std::construct_at.
> >
> > btw are make_obj_using_allocator and std::construct related? The
> > former allocates, the latter does not.
> >
> > On Sun, 2025-05-11 at 12:38 -0400, Arthur O'Dwyer wrote:
> > >
> > > Hi Avi,
> > >
> > > FWIW, I'm not sure P3312 is going anywhere; notice it's still in
> > > EWGI, and the syntax/semantics proposed don't seem very C++-ish
> > > to me.
> > > OTOH, your `std::construct` as written is very similar to the
> > > existing `std::make_obj_using_allocator [1]`; the only difference
> > > is that make_obj_using_allocator takes a first argument of type
> > > std::allocator<T>, whereas yours omits that parameter.
> > > OTOOH, your `std::construct` definitely doesn't achieve your
> > > purpose as written. You wrote a template of 1+K parameters, and
> > > then instantiated it with 1+0 arguments:
> > > https://godbolt.org/z/8dnqThW1Y
> > >
> > > template<class T, class... Args>
> > > T std_construct(Args&&... args) {
> > > return T(std::forward<Args>(args)...);
> > > }
> > >
> > > struct Arg1 {} arg1;
> > > struct Arg2 {} arg2;
> > > struct Arg3 {} arg3;
> > > struct Type1 {
> > > explicit Type1(Arg1, Arg2&, Arg3);
> > > };
> > >
> > > This code allows you to write:
> > >
> > > Type1 (*pf3)(Arg1&&, Arg2&, Arg3&&) = std_construct<Type1, Arg1,
> > > Arg2&, Arg3>;
> > >
> > > But it certainly does not allow you to write either:
> > >
> > >
> > > Type1 (*pf0)() = std_construct<Type1>; // no, Type1 has no zero-
> > > argument constructor
> > > Type1 (*pf3)(Arg1, Arg2&, Arg3) = std_construct<Type1>; // no,
> > > Typ1 has no zero-argument constructorand pf3 doesn't have the
> > > same function type as the zero-argument std_construct<Type1>
> > > auto make_something = std::bind_front(std_construct<Type1>, ~~~);
> > > // certainly not
> > >
> > > What you need for a generic-lambda-style thing is for
> > > std::construct<T> to be a callable object in its own right, like
> > > this:
> > > https://godbolt.org/z/TTbf6cGdx
> > >
> > > All Ranges adaptors are "partially applied templates" similar to
> > > what we're doing here.
> > > Should make_obj_using_allocator be a "partially applicable"
> > > template like this, instead of a "fully applicable only" template
> > > as it currently is?
> > >
> > > Should there be a new "partially applicable" template named
> > > std::make_obj and/or std::construct? (I would prefer the former
> > > name, FWIW, for consistency.)
> > >
> > > Should there be a new core-language feature that permits
> > > automatic handling of the "partial application" of templates,
> > > somehow?
> > > (But this last would run into trouble with backward
> > > compatibility, because your `std::construct<Type1>` from above is
> > > already legal C++ today: it just unambiguously does something
> > > different from whatyou want it to do. Making it automatically
> > > represent a "partial but not complete specification" of
> > > std::construct's template parameter list would change its
> > > meaning, possibly changing the meaning of existing code.)
> > >
> > > my $.02,
> > > –Arthur
> > >
> > >
> > >
> > > On Sun, May 11, 2025 at 7:37 AM Avi Kivity via Std-Proposals
> > > <std-proposals_at_[hidden]> wrote:
> > >
> > >
> > > >
> > > >
> > > > This is superceded by P3312 [1].
> > > > Instead of std::construct<T>(...), write (&T::T)(...).
> > > > [1]
> > > >
> > > https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3312r1.pdf
> > > >
> > > > On Sun, 2024-12-01 at 17:57 +0200, Avi Kivity wrote:
> > > > > Functions and member functions are invocable, but
> > > > > constructors are not.
> > > > >
> > > > > I propose to add
> > > > >
> > > > > template <typename T, typename... Args>
> > > > > T std::construct(Args&&... args) {
> > > > > return T(std::forward<decltype(Args)>(args)...);
> > > > > }
> > > > >
> > > > > With this, we can pass a constructor where other functions
> > > > > can be
> > > > > passed.
> > > > >
> > > > > // build a callback that creates and returns a Type1
> > > > > thing
> > > > > std::function<Type1 (Arg3)> make_somthing =
> > > > > std::bind_front(std::construct<Type1>, arg1, std::ref(arg2));
> > > > >
> > > > > // transform a vector of ints to a vector of some other
> > > > > type
> > > > > auto foo = some_container |
> > > > > std::views::transform(std::construct<AnotherType>) |
> > > > > std::ranges::to<std::vector>();
> >
>
[1] std::make_obj_using_allocator
https://en.cppreference.com/w/cpp/memory/make_obj_using_allocator
forbade dangling references.
On Mon, 2025-07-07 at 01:56 +0000, F. v.S. via Std-Proposals wrote:
>
> construct<T> is roughly equivalent to std::make_from_tuple, except
> that
> - it is (or ought to be) a CPO, and
> - its arguments are not packed.
>
>
> I believe we should impose constraints similar to those of
> std::make_from_tuple to avoid dangling references and undesired
> casts.
>
>
> Thanks,
> F.v.S.
> From: Std-Proposals <std-proposals-bounces_at_[hidden]> on
> behalf of Avi Kivity via Std-Proposals <std-
> proposals_at_[hidden]>
> Sent: Monday, July 7, 2025 4:24
> To: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>; std-
> proposals_at_[hidden] <std-proposals_at_[hidden]>
> Cc: Avi Kivity <avi_at_[hidden]>
> Subject: Re: [std-proposals] std::construct<T>
>
>
> I wrote it up:
>
> https://github.com/avikivity/cpp-std-proposals/blob/std-construct/std-construct.md#proposal-for-stdconstruct-function-object
>
> On Wed, 2025-05-14 at 22:30 +0300, Avi Kivity wrote:
> > You're correct, std::construct should be a variable template with
> > one parameter.
> >
> > Regarding make_obj vs std::construct, obj is not a word, and I
> > think the standard should try hard to use words. I think
> > std::construct is consistent with std::construct_at.
> >
> > btw are make_obj_using_allocator and std::construct related? The
> > former allocates, the latter does not.
> >
> > On Sun, 2025-05-11 at 12:38 -0400, Arthur O'Dwyer wrote:
> > >
> > > Hi Avi,
> > >
> > > FWIW, I'm not sure P3312 is going anywhere; notice it's still in
> > > EWGI, and the syntax/semantics proposed don't seem very C++-ish
> > > to me.
> > > OTOH, your `std::construct` as written is very similar to the
> > > existing `std::make_obj_using_allocator [1]`; the only difference
> > > is that make_obj_using_allocator takes a first argument of type
> > > std::allocator<T>, whereas yours omits that parameter.
> > > OTOOH, your `std::construct` definitely doesn't achieve your
> > > purpose as written. You wrote a template of 1+K parameters, and
> > > then instantiated it with 1+0 arguments:
> > > https://godbolt.org/z/8dnqThW1Y
> > >
> > > template<class T, class... Args>
> > > T std_construct(Args&&... args) {
> > > return T(std::forward<Args>(args)...);
> > > }
> > >
> > > struct Arg1 {} arg1;
> > > struct Arg2 {} arg2;
> > > struct Arg3 {} arg3;
> > > struct Type1 {
> > > explicit Type1(Arg1, Arg2&, Arg3);
> > > };
> > >
> > > This code allows you to write:
> > >
> > > Type1 (*pf3)(Arg1&&, Arg2&, Arg3&&) = std_construct<Type1, Arg1,
> > > Arg2&, Arg3>;
> > >
> > > But it certainly does not allow you to write either:
> > >
> > >
> > > Type1 (*pf0)() = std_construct<Type1>; // no, Type1 has no zero-
> > > argument constructor
> > > Type1 (*pf3)(Arg1, Arg2&, Arg3) = std_construct<Type1>; // no,
> > > Typ1 has no zero-argument constructorand pf3 doesn't have the
> > > same function type as the zero-argument std_construct<Type1>
> > > auto make_something = std::bind_front(std_construct<Type1>, ~~~);
> > > // certainly not
> > >
> > > What you need for a generic-lambda-style thing is for
> > > std::construct<T> to be a callable object in its own right, like
> > > this:
> > > https://godbolt.org/z/TTbf6cGdx
> > >
> > > All Ranges adaptors are "partially applied templates" similar to
> > > what we're doing here.
> > > Should make_obj_using_allocator be a "partially applicable"
> > > template like this, instead of a "fully applicable only" template
> > > as it currently is?
> > >
> > > Should there be a new "partially applicable" template named
> > > std::make_obj and/or std::construct? (I would prefer the former
> > > name, FWIW, for consistency.)
> > >
> > > Should there be a new core-language feature that permits
> > > automatic handling of the "partial application" of templates,
> > > somehow?
> > > (But this last would run into trouble with backward
> > > compatibility, because your `std::construct<Type1>` from above is
> > > already legal C++ today: it just unambiguously does something
> > > different from whatyou want it to do. Making it automatically
> > > represent a "partial but not complete specification" of
> > > std::construct's template parameter list would change its
> > > meaning, possibly changing the meaning of existing code.)
> > >
> > > my $.02,
> > > –Arthur
> > >
> > >
> > >
> > > On Sun, May 11, 2025 at 7:37 AM Avi Kivity via Std-Proposals
> > > <std-proposals_at_[hidden]> wrote:
> > >
> > >
> > > >
> > > >
> > > > This is superceded by P3312 [1].
> > > > Instead of std::construct<T>(...), write (&T::T)(...).
> > > > [1]
> > > >
> > > https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3312r1.pdf
> > > >
> > > > On Sun, 2024-12-01 at 17:57 +0200, Avi Kivity wrote:
> > > > > Functions and member functions are invocable, but
> > > > > constructors are not.
> > > > >
> > > > > I propose to add
> > > > >
> > > > > template <typename T, typename... Args>
> > > > > T std::construct(Args&&... args) {
> > > > > return T(std::forward<decltype(Args)>(args)...);
> > > > > }
> > > > >
> > > > > With this, we can pass a constructor where other functions
> > > > > can be
> > > > > passed.
> > > > >
> > > > > // build a callback that creates and returns a Type1
> > > > > thing
> > > > > std::function<Type1 (Arg3)> make_somthing =
> > > > > std::bind_front(std::construct<Type1>, arg1, std::ref(arg2));
> > > > >
> > > > > // transform a vector of ints to a vector of some other
> > > > > type
> > > > > auto foo = some_container |
> > > > > std::views::transform(std::construct<AnotherType>) |
> > > > > std::ranges::to<std::vector>();
> >
>
[1] std::make_obj_using_allocator
https://en.cppreference.com/w/cpp/memory/make_obj_using_allocator
Received on 2025-07-07 09:08:54