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...});
(`std::initializer_list<T>{vals...}`, that is, to avoid the pitfall of CTAD deducing the wrong type when T is a specialization of `initializer_list` and there's only one element in `vals`.)
std::ranges::find(vector_of_pairs, {1,2})
and not things like
std::ranges::set_intersection(vector_of_ints, {1,2,3})
. I thought there'd been a little discussion of the latter, but I don't see such discussion in P2248R8, anyway.
Additionally, it might be more valuable if it could return `*this` instead of `void` [...]
which can provide a chain operation for users
Definitely not. That kind of "chaining" is essentially never useful in practice, and merely serves to (1) make the function's implementation one line longer and (2) make the codegen/register-pressure inside the function very marginally worse. It also leads to antipatterns on the caller side: it tempts users to write
Object f(Object o) { return o.chained(); } // makes a copy of `o`
as opposed to forcing the more efficient
Object f(Object o) { o.chained(); return o; } // moves from `o`
And, unless I'm mistaken, `.append_range` is part of the container requirements now, which means users will sometimes have to implement it themselves for their own containers. We must not force these infelicities and inefficiencies on them; we must at least allow them to write optimal code.
–Arthur