C++ Logo

std-proposals

Advanced search

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

From: Avi Kivity <avi_at_[hidden]>
Date: Tue, 15 Jul 2025 16:19:09 +0300
On Tue, 2025-07-15 at 15:21 +0300, Ville Voutilainen wrote:
> On Tue, 15 Jul 2025 at 15:12, Avi Kivity via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> >
> > Previous thread:
> > https://lists.isocpp.org/std-proposals/2024/12/11641.php
> >
> > git:
> > https://github.com/avikivity/cpp-std-proposals/blob/main/std-construct.md
> >
> > Proposal for std::construct Function Object
> >
> > I. Motivation
> >
> > C++ users can convert member functions to funtion objects with
> > std::mem_fn(), partially bind arguments to functions or function
> > objects with std::bind, std::bind_front(), and std::bind_back(),
> > type-erase them with std::function<>, and use them to transform
> > ranges with std::views::transform. But none of that can be done
> > directly to class constructors; a helper function must be used to
> > "downgrade" the constructor into a function.
> > The proposed std::construct<> is a utility function object that
> > provides a convenient, generic mechanism to convert a constructor
> > overload set into a function object, thereby allowing all the
> > existing tooling for function objects to be brought to bear on it.
> >
> > II. Example Problem
> >
> > Imagine you have a range of size_t and you wish to return a vector
> > of vectors, with the sizes given from the given range. Naive code
> > can look like:
> >
> > std::vector<std::vector<int>> result;
> > result.reserve(std::distance(input));
> > for (auto sz : input) {
> > result.emplace_back(sz);
> > }
> >
> > However, this is unsatisfying. The input range may be an
> > input_range, which does not afford two passes (one for
> > std::distance, one for the for loop). The emplace_back loop is less
> > efficient than constructing the vector from a range.
> > A modern range-based solution would look like
> >
> > auto result = input
> > | std::views::transform([] (size_t sz) {
> > return std::vector<int>(sz);
> > }
> > | std::ranges::to<std::vector>();
> >
> > This is still unsatisfying, as the lambda is not concise.
>
> I don't quite follow what this means. The lambda is not concise? So
> what?
>
> Perhaps show what the solution looks like with std::construct
> applied?


It's shown later in the proposal.

    // Updated example from above
    auto result = input
        | std::views::transform(std::construct<std::vector<int>>)
        | std::ranges::to<std::vector>();

As to why conciseness is important, well, why do we have lambdas? We
could create a new struct with a constructor and operator(), but we
prefer the conciseness of lambdas.

It's similar to some prefer passing a member function pointer to
std::views::transform rather than a lambda calling the function.


Received on 2025-07-15 13:19:18