Title
Exceptions from std::seed_seq operations
Status
c++14
Section
[rand.util.seedseq]
Submitter
Daniel Krügler

Created on 2012-08-18.00:00:00 last changed 123 months ago

Messages

Date: 2013-09-29.10:45:42

Proposed resolution:

This wording is relative to N3376.

  1. Edit [rand.util.seedseq] p1 as indicated:

    -1- No function described in this section [rand.util.seedseq] throws an exception.

  2. Edit [rand.util.seedseq] around p2 as indicated:

    seed_seq();
    

    -2- Effects: Constructs a seed_seq object as if by default-constructing its member v.

    -?- Throws: Nothing.

  3. Edit [rand.util.seedseq] around p7 as indicated:

    template<class RandomAccessIterator>
      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, with s = v.size() and n = end - begin, fills the supplied range [begin, end) according to the following algorithm […]

    -?- Throws: What and when RandomAccessIterator operations of begin and end throw.

  4. Edit [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.

  5. Edit [rand.util.seedseq] around p11 as indicated:

    template<class OutputIterator>
      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 value rt of type result_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 of dest throw.

Date: 2013-09-15.00:00:00

[ 2013-09-29, Chicago ]

Apply to Working Paper

Date: 2013-04-15.00:00:00

[ 2013-04-20, Bristol ]

Open an editorial issue on the exception wording ("Throws: What and when").

Solution: move to tentatively ready.

Date: 2012-08-19.16:32:07

[rand.util.seedseq] p1 says upfront:

No function described in this section [rand.util.seedseq] throws an exception.

This constraint seems non-implementable to me when looking especially at the members

template<class T>
seed_seq(initializer_list<T> il);

template<class InputIterator>
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<class RandomAccessIterator>
void generate(RandomAccessIterator begin, RandomAccessIterator end);

template<class OutputIterator>
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 [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 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() and param() to ensure that the algorithm itself is a nothrow operation, which is especially for generate() important, because the templates specified in [rand.eng] and [rand.adapt] also depend on this property indirectly, which is further discussed in LWG 2181.

Howard:

I suggest to use a different form for the exception specification, something similar to [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 [rand.util.canonical].

History
Date User Action Args
2014-02-20 13:20:35adminsetstatus: wp -> c++14
2013-09-29 10:45:42adminsetmessages: + msg6659
2013-09-29 10:45:42adminsetstatus: voting -> wp
2013-09-23 13:24:31adminsetstatus: ready -> voting
2013-05-20 16:25:01adminsetmessages: + msg6507
2013-05-20 16:25:01adminsetstatus: new -> ready
2012-08-19 00:36:54adminsetmessages: + msg6128
2012-08-18 00:00:00admincreate