Date: Sat, 15 Nov 2025 17:43:46 +0000
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.
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 17:44:03
