C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::construct<T>

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Wed, 16 Jul 2025 16:34:19 -0400
On Wed, Jul 16, 2025 at 1:02 PM Arthur O'Dwyer via Std-Proposals
<std-proposals_at_[hidden]> 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`, 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.

It wasn't done because why not. Things like `std::less` and so forth
*should not* have been templates to begin with. They should have used
overloaded operators.

You said "std::set<T, std::less<T>> Just Works". Except it doesn't. It
doesn't provide the ability to use non-symmetric comparisons
(https://en.cppreference.com/w/cpp/functional.html#Transparent_function_objects).
To get that, you have to use `std::set<T, std::less<>>`, which
declares `is_transparent`.

Note that `std::ranges::less` and its ilk are also types, not templates.


>
> (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>();
>
> 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
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2025-07-16 20:34:36