Issue 2180: Exceptions from std::seed_seq operations (original) (raw)
This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++14 status.
2180. Exceptions from std::seed_seq
operations
Section: 29.5.8.1 [rand.util.seedseq] Status: C++14 Submitter: Daniel Krügler Opened: 2012-08-18 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [rand.util.seedseq].
View all issues with C++14 status.
Discussion:
29.5.8.1 [rand.util.seedseq] p1 says upfront:
No function described in this section 29.5.8.1 [rand.util.seedseq] throws an exception.
This constraint seems non-implementable to me when looking especially at the members
template seed_seq(initializer_list il);
template seed_seq(InputIterator begin, InputIterator end);
which have the effect of invoking v.push_back()
for the exposition-only member of type std::vector
(or its equivalent) over all elements of the provided range, so out-of-memory exceptions are always possible and the seed_seq
object doesn't seem to be constructible this way.
In addition to the potential lack-of-resources problem, the operations of InputIterator
might also throw exceptions.
Aside to that it should me mentioned, that a default constructor of vector<uint_least32_t>
in theory can also throw exceptions, even though this seems less of a problem to me in this context, because such an implementation could easily use a different internal container in seed_seq
that can hold this no-throw exception guarantee.
Secondly, a slightly different problem category related to exceptions occurs for the member templates
template void generate(RandomAccessIterator begin, RandomAccessIterator end);
template void param(OutputIterator dest) const;
where the actual operations performed by the implementation would never need to throw, but since they invoke operations of a user-provided customization point, the overall operation, like for example
copy(v.begin(), v.end(), dest);
could also throw exceptions. In this particular example we can just think of a std::back_insert_iterator
applied to a container that needs to allocate its elements used as the type for OutputIterator
.
Even though Clause 29 [numerics] has mostly stronger exception constraints than other parts of the library the here discussed are overrestrictive, especially since no operation of std::seed_seq
except the template generate
is actually needed within the library implementation, as mentioned in the discussion of LWG 2124(i).
I suggest to remove the general no-exception constraints for operations of std::seed_seq
except for member size()
and the default constructor and to provide specific wording for generate()
andparam()
to ensure that the algorithm itself is a nothrow operation, which is especially forgenerate()
important, because the templates specified in 29.5.4 [rand.eng] and 29.5.5 [rand.adapt] also depend on this property indirectly, which is further discussed in LWG 2181(i).
Howard:
I suggest to use a different form for the exception specification, something similar to 22.10.15.4 [func.bind.bind] p4:
Throws: Nothing unless an operation on
RandomAccessIterator
throws an exception.
Daniel:
The currently suggested "what and when" form seems a bit more specific and harmonizes with the form used for function template generate_canonical
from 29.5.8.2 [rand.util.canonical].
[2013-04-20, Bristol]
Open an editorial issue on the exception wording ("Throws: What and when").
Solution: move to tentatively ready.
[2013-09-29, Chicago]
Apply to Working Paper
Proposed resolution:
This wording is relative to N3376.
- Edit 29.5.8.1 [rand.util.seedseq] p1 as indicated:
-1- No function described in this section 29.5.8.1 [rand.util.seedseq] throws an exception. - Edit 29.5.8.1 [rand.util.seedseq] around p2 as indicated:
seed_seq();
-2- Effects: Constructs a
seed_seq
object as if by default-constructing its memberv
.-?- Throws: Nothing.
- Edit 29.5.8.1 [rand.util.seedseq] around p7 as indicated:
template
void generate(RandomAccessIterator begin, RandomAccessIterator end);-7- Requires:
RandomAccessIterator
shall meet the requirements of a mutable random access iterator (Table 111) type. Moreover,iterator_traits<class RandomAccessIterator>::value_type
shall denote an unsigned integer type capable of accommodating 32-bit quantities.-8- Effects: Does nothing if
begin == end
. Otherwise, withs = v.size()
andn = end - begin
, fills the supplied range[begin, end)
according to the following algorithm […]-?- Throws: What and when
RandomAccessIterator
operations ofbegin
andend
throw. - Edit 29.5.8.1 [rand.util.seedseq] around p9 as indicated:
size_t size() const;
-9- Returns: The number of 32-bit units that would be returned by a call to
param()
.-??- Throws: Nothing.
-10- Complexity: constant time.
- Edit 29.5.8.1 [rand.util.seedseq] around p11 as indicated:
template
void param(OutputIterator dest) const;-11- Requires:
OutputIterator
shall satisfy the requirements of an output iterator (Table 108) type. Moreover, the expression*dest = rt
shall be valid for a valuert
of typeresult_type
.-12- Effects: Copies the sequence of prepared 32-bit units to the given destination, as if by executing the following statement:
copy(v.begin(), v.end(), dest);
-??- Throws: What and when
OutputIterator
operations ofdest
throw.