This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
std::ranges::destroy should allow exceptionsSection: 20.2.2 [memory.syn] Status: New Submitter: Ruslan Arutyunyan Opened: 2025-10-24 Last modified: 2025-10-25
Priority: Not Prioritized
View all other issues in [memory.syn].
View all issues with New status.
Discussion:
The serial std::ranges::destroy algorithm is marked as noexcept. However, the parallel
counterpart should not be marked noexcept.
destroy algorithm when called
with the standard execution policies (seq, unseq, par, par_unseq), the
implementation-defined policies for parallel algorithms are allowed by the C++ standard,
and it is up to the particular execution policy to decide which exceptions can be thrown
from parallel algorithms.
Proposed resolution:
This wording is relative to N5014.
Modify 20.2.2 [memory.syn], header <memory> synopsis, as indicated:
[Drafting note: There are no further prototype definitions for the affected
execution-policyoverloads in 26.11.9 [specialized.destroy].]
[…] // 26.11.9, 26.11.9 [specialized.destroy] template<class T> constexpr void destroy_at(T* location); // freestanding template<class NoThrowForwardIterator> constexpr void destroy(NoThrowForwardIterator first, // freestanding NoThrowForwardIterator last); template<class ExecutionPolicy, class NoThrowForwardIterator> void destroy(ExecutionPolicy&& exec, // freestanding-deleted, NoThrowForwardIterator first, // see 26.3.5 [algorithms.parallel.overloads] NoThrowForwardIterator last); template<class NoThrowForwardIterator, class Size> constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, // freestanding Size n); template<class ExecutionPolicy, class NoThrowForwardIterator, class Size> NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec, // freestanding-deleted, NoThrowForwardIterator first, Size n); // see 26.3.5 [algorithms.parallel.overloads] namespace ranges { template<destructible T> constexpr void destroy_at(T* location) noexcept; // freestanding template<nothrow-input-iterator I, nothrow-sentinel-for <I> S> requires destructible<iter_value_t<I>> constexpr I destroy(I first, S last) noexcept; // freestanding template<nothrow-input-range R> requires destructible<range_value_t<R>> constexpr borrowed_iterator_t<R> destroy(R&& r) noexcept; // freestanding template<nothrow-input-iterator I> requires destructible<iter_value_t<I>> constexpr I destroy_n(I first, iter_difference_t<I> n) noexcept; // freestanding template<execution-policy Ep, nothrow-random-access-iterator I, nothrow-sized-sentinel-for <I> S> requires destructible<iter_value_t<I>> I destroy(Ep&& exec, I first, S last)noexcept; // freestanding-deleted, // see 26.3.5 [algorithms.parallel.overloads] template<execution-policy Ep, nothrow-sized-random-access-range R> requires destructible<range_value_t<R>> borrowed_iterator_t<R> destroy(Ep&& exec, R&& r)noexcept; // freestanding-deleted, // see 26.3.5 [algorithms.parallel.overloads] template<execution-policy Ep, nothrow-random-access-iterator I> requires destructible<iter_value_t<I>> I destroy_n(Ep&& exec, I first, iter_difference_t<I> n)noexcept; // freestanding-deleted, // see 26.3.5 [algorithms.parallel.overloads] } […]