C++ Logo

std-proposals

Advanced search

Re: [std-proposals] better container::append_range?

From: Hewill Kang <hewillk_at_[hidden]>
Date: Sun, 16 Nov 2025 02:10:18 +0800
Thank you for the valuable feedback.

string::apend_range returning string& is consistent with string::append
> returning string&.
> vector::append_range returning void is consistent with vector::append
> returning void.
> I'm not sure why we would only want to change vector::append_range, making
> it inconsistent, rather than also changing vector::append.


 Yes, but we don't really need to be consistent with vector::append. Give
append_range the new C++23 API, right?
It's like how emplace_back and push_back both returned void at first, but
after C++17, emplace_back returned T&. If this is valuable, shouldn't it be
done?

If you have three separate ranges, you can just use:
> v.append_range(views::concat(r1, r2, r3));


Then I would have to rely on the entire <ranges>, which doesn't seem
worthwhile; Or writing `v.append(xxx)` three times separately results in
more typing.

Jonathan Wakely <cxx_at_[hidden]> 於 2025年11月16日 週日 上午1:44寫道:

>
>
> On Sat, 15 Nov 2025 at 06:33, Hewill Kang via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Hi all,
>>
>> In C++23, we can use `append_range` to append ranges to a container more
>> intuitively and simply. Its function signature is as follows (from
>> https://eel.is/c++draft/containers)
>>
>> ```
>> template<container-compatible-range<T> R>
>> constexpr void append_range(R&& rg);
>> ```
>>
>> So we can:
>>
>> ```
>> std::vector<int> v;
>> v.append_range(std::views::iota(0, 5));
>> ```
>>
>> I think there are two areas for improvement.
>> First, it would be great to provide a default template to support
>> `initializer_list`:
>>
>> ```
>> template<container-compatible-range<T> R = initializer_list<T>>
>> constexpr void append_range(R&& rg);
>> ```
>>
>> which would make it more convenient for users:
>>
>> ```
>> std::vector<int> v;
>> v.append_range({1, 2, 3, 4});
>> ```
>>
>
> How often do you want to append a hardcoded list of values though?
>
> Initializer lists are useful for construction, when you often want to
> populate a container to a known set of values. I can't think of many times
> when I've wanted to append a known set of values to an existing container.
>
> Maybe you would want to use it in a variadic function template to append a
> pack:
> v.append_range({vals...});
> But even that seems quite niche, and you can do:
> v.append_range(std::initializer_list{vals...});
>
> If you don't need this often, the additional typing needed isn't too
> inconvenient.
>
>
>> Additionally, it might be more valuable if it could return
>> `*this` instead of `void`:
>>
>> ```
>> template<container-compatible-range<T> R = initializer_list<T>>
>> constexpr vector& append_range(R&& rg);
>> ```
>>
>> which can provide a chain operation for users, since
>> `string::append_range` already returns `string&`:
>>
>> ```
>> std::vector<int> v;
>> v.append_range({1, 2, 3}).append_range({4, 5, 6})..append_range({7, 8,
>> 9});
>> ```
>>
>>
> string::apend_range returning string& is consistent with string::append
> returning string&.
>
> vector::append_range returning void is consistent with vector::append
> returning void.
>
> I'm not sure why we would only want to change vector::append_range, making
> it inconsistent, rather than also changing vector::append.
>
> And is chaining those append operations useful often? Just because it's
> possible to support that, doesn't mean it would be useful.
>
> The example above with hardcoded values is silly, you would just do
> {1,2,3,4,5,6,7,8,9}.
> If you have three separate ranges, you can just use:
> v.append_range(views::concat(r1, r2, r3));
>
> I don't think either of these would add a lot of value in practice.
>

Received on 2025-11-15 18:10:33