std::ranges::destroy_n() algorithm
- od C++20
- Simplified
- Detailed
// (1)
constexpr I destroy_n( I first, std::iter_difference_t<I> n ) noexcept;
The type of arguments are generic and have following constraints:
I-no-throw-input-iterator
Additionally, each overload has the following constraints:
- (1)
std::destructible<std::iter_value_t<I>>
// (1)
template< no-throw-input-iterator I >
requires std::destructible<std::iter_value_t<I>>
constexpr I destroy_n( I first, std::iter_difference_t<I> n ) noexcept;
Destroys the n objects in the range starting at first, equivalent to
return std::ranges::destroy(std::counted_iterator(first, n), std::default_sentinel).base();
The function-like entities described on this page are niebloids.
Parameters
first | The beginning of the range of elements to destroy. |
n | The number of elements to destroy. |
Return value
The end of the range of objects that has been destroyed.
Complexity
Linear in n.
Exceptions
The exception thrown on construction of the elements in the destination range, if any.
Possible implementation
destroy_n(1)
struct destroy_n_fn
{
template<no-throw-input-iterator I>
requires std::destructible<std::iter_value_t<I>>
constexpr I operator()(I first, std::iter_difference_t<I> n) const noexcept
{
for (; n != 0; (void)++first, --n)
std::ranges::destroy_at(std::addressof(*first));
return first;
}
};
inline constexpr destroy_n_fn destroy_n{};
Examples
#include <iostream>
#include <memory>
#include <new>
struct Tracer
{
int value;
~Tracer() { std::cout << value << " destructed\n"; }
};
int main()
{
alignas(Tracer) unsigned char buffer[sizeof(Tracer) * 8];
for (int i = 0; i < 8; ++i)
new(buffer + sizeof(Tracer) * i) Tracer{i}; //manually construct objects
auto ptr = std::launder(reinterpret_cast<Tracer*>(buffer));
std::ranges::destroy_n(ptr, 8);
}
0 destructed
1 destructed
2 destructed
3 destructed
4 destructed
5 destructed
6 destructed
7 destructed
Hover to see the original license.