Date: Thu, 17 Jul 2025 11:40:47 +0300
On Wed, 2025-07-16 at 13:02 -0400, Arthur O'Dwyer wrote:
> On Tue, Jul 15, 2025 at 4:50 PM Avi Kivity via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> > On Tue, 2025-07-15 at 15:59 +0200, Jan Schultke wrote:
> > > I think it's well-motivated; we have function objects for
> > > std::plus/+
> > > and other sort of builtin things that you cannot (always) for a
> > > function pointer to, and this fits right in with those.
> > >
> > > However, std::construct is a bad name. You're basically making a
> > > callable type in the style of std::plus and std::less; [...]
> >
> >
> > [...] std::construction<T> sounds wrong to me. It's a function
> > object, so it should be a verb, not a noun. Although std::plus
> > isn't a verb.
> >
>
>
> There's another unfortunate difference between this thing and
> std::{plus,equal_to,...}.
> The existing <functional> wrappers — with one very sad exception —
> are all class templates, not global variables, historically because
> types are easier for the compiler to deal with (they don't take space
> in the .o file and require linker action) and because types are
> strictly easier to use with the STL (e.g. `std::set<T, std::less<T>>`
> Just Works).
> The sad exception is `std::compare_three_way` [1], which is a class,
> not a class template. I guess LEWG just thought "let's try something
> a little different this time, for the heck of it." But gratuitous
> inconsistency is never a good idea.
>
> (Writing "constructx" for "construct/constructor/construction"; I
> don't care much about that bikeshed.)
>
> I would recommend making `std::constructx<T>` a class template and
> requiring people to write parens when they want an object of that
> type:
>
> auto result = input
> | std::views::transform(std::constructx<T>())
> | std::ranges::to<std::vector>();
Agree with that, will make the change after collecting more feedback.
It looks odd to write std::constructx<T>()(...), but that's hardly the
intended use case.
>
> This even allows people to use it in crazy ways with the existing STL. I haven't got a non-crazy use-case on the tip of my tongue, but consider something like
> struct Less {
> bool v_;
> operator bool() const { return v_; }
> explicit Less(int a, int b) : v_(a < b) {}
> };
> std::set<int, std::constructx<Less>> s;
>
> This says, "My comparator is a thing, such that when you invoke it with two arguments, it returns a Less constructed from those two arguments (which `set` then converts to bool)."
> https://godbolt.org/z/vsvqadba5
> Btw, that conversion-to-bool seems to be explicit or contextual in libc++, but implicit in libstdc++. I don't know if libstdc++'s behavior is conforming-but-draconian, or a bug. But of course this is a silly corner case anyway.
>
> –Arthur
[1] `std::compare_three_way`
https://en.cppreference.com/w/cpp/utility/compare/compare_three_way
> On Tue, Jul 15, 2025 at 4:50 PM Avi Kivity via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> > On Tue, 2025-07-15 at 15:59 +0200, Jan Schultke wrote:
> > > I think it's well-motivated; we have function objects for
> > > std::plus/+
> > > and other sort of builtin things that you cannot (always) for a
> > > function pointer to, and this fits right in with those.
> > >
> > > However, std::construct is a bad name. You're basically making a
> > > callable type in the style of std::plus and std::less; [...]
> >
> >
> > [...] std::construction<T> sounds wrong to me. It's a function
> > object, so it should be a verb, not a noun. Although std::plus
> > isn't a verb.
> >
>
>
> There's another unfortunate difference between this thing and
> std::{plus,equal_to,...}.
> The existing <functional> wrappers — with one very sad exception —
> are all class templates, not global variables, historically because
> types are easier for the compiler to deal with (they don't take space
> in the .o file and require linker action) and because types are
> strictly easier to use with the STL (e.g. `std::set<T, std::less<T>>`
> Just Works).
> The sad exception is `std::compare_three_way` [1], which is a class,
> not a class template. I guess LEWG just thought "let's try something
> a little different this time, for the heck of it." But gratuitous
> inconsistency is never a good idea.
>
> (Writing "constructx" for "construct/constructor/construction"; I
> don't care much about that bikeshed.)
>
> I would recommend making `std::constructx<T>` a class template and
> requiring people to write parens when they want an object of that
> type:
>
> auto result = input
> | std::views::transform(std::constructx<T>())
> | std::ranges::to<std::vector>();
Agree with that, will make the change after collecting more feedback.
It looks odd to write std::constructx<T>()(...), but that's hardly the
intended use case.
>
> This even allows people to use it in crazy ways with the existing STL. I haven't got a non-crazy use-case on the tip of my tongue, but consider something like
> struct Less {
> bool v_;
> operator bool() const { return v_; }
> explicit Less(int a, int b) : v_(a < b) {}
> };
> std::set<int, std::constructx<Less>> s;
>
> This says, "My comparator is a thing, such that when you invoke it with two arguments, it returns a Less constructed from those two arguments (which `set` then converts to bool)."
> https://godbolt.org/z/vsvqadba5
> Btw, that conversion-to-bool seems to be explicit or contextual in libc++, but implicit in libstdc++. I don't know if libstdc++'s behavior is conforming-but-draconian, or a bug. But of course this is a silly corner case anyway.
>
> –Arthur
[1] `std::compare_three_way`
https://en.cppreference.com/w/cpp/utility/compare/compare_three_way
Received on 2025-07-17 08:40:55