Date: Sun, 01 Dec 2024 20:43:21 +0200
On Sun, 2024-12-01 at 21:25 +0300, Andrey Semashev wrote:
> On December 1, 2024 7:57:45 PM Avi Kivity <avi_at_[hidden]> wrote:
>
> > On Sun, 2024-12-01 at 19:11 +0300, Andrey Semashev via Std-
> > Proposals
> > wrote:
> > > On December 1, 2024 6:57:16 PM Avi Kivity via Std-Proposals
> > > <std-proposals_at_[hidden]> 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>();
> > >
> > > Binding a function pointer is less efficient than a function
> > > object.
> >
> > Typically, inlining will remove the difference.
>
> The function pointer must still increase the size of the binder,
> which may
> make it too large to fit in e. g. std::function small buffer.
>
> And whether the compiler is able to devirtualize the call is more of
> a
> question than with a function object with an inline operator().
>
> > Or we can make it a
> > niebloid.
>
> Sorry, I don't know what this means.
>
A technique used in std::ranges to avoid such pointers-to-functions.
template <typename T>
struct _Impl_construct
template <typename... Args>
static T operator()(Args... args) { return
T(std::forward<Args>(args)...); }
};
template <typename T>
inline _Impl_construct construct;
> >
> >
> > > And
> > > given that lambdas are an easy way to create function objects, I
> > > don't
> > > really see the benefits of the proposal.
> >
> >
> > I believe that writing
> >
> > std::views::transform(std::construct<AnotherType>)
> >
> > is more readable than
> >
> > std::views::transform([] (auto&& x) { return
> > AnotherType<std::forward<decltype(x)>(x); });
>
> I think this is not equivalent to the original example. Is
> AnotherType a
> template?
>
I mistyped, sorry.
std::views::transform([] (auto&& x) { return
AnotherType(std::forward<decltype(x)>(x)); });
The intent is to construct an object of type AnotherType using a single
parameter of unknown type.
> On December 1, 2024 7:57:45 PM Avi Kivity <avi_at_[hidden]> wrote:
>
> > On Sun, 2024-12-01 at 19:11 +0300, Andrey Semashev via Std-
> > Proposals
> > wrote:
> > > On December 1, 2024 6:57:16 PM Avi Kivity via Std-Proposals
> > > <std-proposals_at_[hidden]> 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>();
> > >
> > > Binding a function pointer is less efficient than a function
> > > object.
> >
> > Typically, inlining will remove the difference.
>
> The function pointer must still increase the size of the binder,
> which may
> make it too large to fit in e. g. std::function small buffer.
>
> And whether the compiler is able to devirtualize the call is more of
> a
> question than with a function object with an inline operator().
>
> > Or we can make it a
> > niebloid.
>
> Sorry, I don't know what this means.
>
A technique used in std::ranges to avoid such pointers-to-functions.
template <typename T>
struct _Impl_construct
template <typename... Args>
static T operator()(Args... args) { return
T(std::forward<Args>(args)...); }
};
template <typename T>
inline _Impl_construct construct;
> >
> >
> > > And
> > > given that lambdas are an easy way to create function objects, I
> > > don't
> > > really see the benefits of the proposal.
> >
> >
> > I believe that writing
> >
> > std::views::transform(std::construct<AnotherType>)
> >
> > is more readable than
> >
> > std::views::transform([] (auto&& x) { return
> > AnotherType<std::forward<decltype(x)>(x); });
>
> I think this is not equivalent to the original example. Is
> AnotherType a
> template?
>
I mistyped, sorry.
std::views::transform([] (auto&& x) { return
AnotherType(std::forward<decltype(x)>(x)); });
The intent is to construct an object of type AnotherType using a single
parameter of unknown type.
Received on 2024-12-01 18:43:24