C++ Logo

std-proposals

Advanced search

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

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Wed, 16 Jul 2025 13:02:23 -0400
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`
<https://en.cppreference.com/w/cpp/utility/compare/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.

(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

Received on 2025-07-16 17:02:41