C++ Logo

std-proposals

Advanced search

Re: [std-proposals] ranges::to<view_type>?

From: Hewill Kang <hewillk_at_[hidden]>
Date: Sun, 15 Dec 2024 03:45:07 +0800
>
> (1) It won't just construct T from Args...; it will do a whole complicated
> overload resolution and possibly end up constructing T from
> `std::from_range_t, Args...` or some other bag of arguments entirely, which
> is going to be error-prone and confusing


I don't think this is a disadvantage, it's actually the power of ranges::to
IMO. because it can choose the appropriate way to construct the destination
object. Note that ranges::to can specify *any* type other than view type,
even non-range type, so I don't think removing the view restriction can
introduce any significant confusion.

(2) `ranges::to<T>` is constrained to work only when `T` is a non-view
> range type, plus certain other constraints.


ranges::to works with any non-view range class type, even
ranges::to<tuple>. Removing the view restriction would make (2) work as it
*should*.
Also, C++26 makes optional a view, it turns out that we can no longer write
ranges::to<optional>, which is unfortunate since we might want to transform
vector<optional<int>> into optional<vector<int>>.

If ranges::to can specify any non-view class type, then why do we just
relax and allow it to specify any class type?

Thanks,
Hewill

Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]> 於 2024年12月14日 週六 上午6:21寫道:

> On Fri, Dec 13, 2024 at 1:33 PM Hewill Kang via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Currently, the template parameter C of ranges::to<C>(r)
>> <https://en.cppreference.com/w/cpp/ranges/to> cannot be a view, which
>> means we cannot write the following:
>>
>> string s;
>> auto sv = ranges::to<string_view>(s); // error, string_view is view
>>
>> I find this to be very inconvenient, as such limitation really prohibits
>> a lot of useful use cases:
>>
>> string_view s = "1.2.3.4";
>> auto r = s | views::split('.')
>> | views::transform(ranges::to<std::string_view>()); //
>> error
>>
>
> I'm not convinced that this is a proper use of `ranges::to`.
> It *would* be a proper use of Avi Kivity's recently proposed
> `std::construct`,
> <https://lists.isocpp.org/std-proposals/2024/12/11641.php> which is
> explicitly designed to "lift" a constructor into a callable, and for no
> other purpose, as in:
>
> namespace std {
> template<class T> struct construct {
> static T operator()(auto&&... args) { return
> T(decltype(args)(args)...); }
> };
> } // namespace std
>
> auto r = s | views::split('.') |
> views::transform(std::construct<std::string_view>());
>
> Now, it's true that `ranges::to<T>` can already be used as a poor man's
> version of `std::construct<T>`, but it suffers from two big limitations in
> that respect:
>
> (1) It won't just construct T from Args...; it will do a whole complicated
> overload resolution and possibly end up constructing T from
> `std::from_range_t, Args...` or some other bag of arguments entirely, which
> is going to be error-prone and confusing, if what you really want is
> *just* to lift the constructor into a callable. That is, `ranges::to`
> cannot be used as a poor man's std::construct *in generic code*. (Still,
> it *can* be used *as `ranges::to`* in generic code!)
>
> (2) `ranges::to<T>` is constrained to work only when `T` is a non-view
> range type, plus certain other constraints.
> auto a = s | std::ranges::to<std::string>(); // OK
> auto b = s | std::ranges::to<std::string_view>(); // ill-formed
> SFINAE-friendly
> auto c = s | std::ranges::to<std::filesystem::path>(); // ill-formed
> hard-error
>
> Your proposal asks to patch up a very tiny piece of (2), while leaving
> most of (2) and all of (1) unfixed. That doesn't seem like a good idea to
> me.
>
> Let `ranges::to` be `ranges::to`; if you want a way to lift a constructor
> into a callable, don't misuse `ranges::to` for that purpose, but rather,
> design a new thing that does *only* that lifting.
>
> HTH,
> –Arthur
>

Received on 2024-12-15 15:47:03