Title
Exceptions from seed sequence operations
Status
c++17
Section
[rand.req.seedseq] [rand.eng] [rand.adapt]
Submitter
Daniel Krügler

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

Messages

Date: 2015-10-31.16:48:48

Proposed resolution:

This wording is relative to N4527.

  1. Edit the contents of sub-clause [rand.eng] as indicated:

    -1- […]

    -2- Except where specified otherwise, the complexity of each function specified in this section [rand.eng] is constant.

    -3- Except where specified otherwise, no function described in this section [rand.eng] throws an exception.

    -?- Every function described in this section [rand.eng] that has a function parameter q of type Sseq& for a template type parameter named Sseq that is different from type std::seed_seq throws what and when the invocation of q.generate throws.

    […]

  2. Edit the contents of sub-clause [rand.adapt.general] as indicated:

    -1- […]

    -2- Except where specified otherwise, the complexity of each function specified in this section [rand.adapt] is constant.

    -3- Except where specified otherwise, no function described in this section [rand.adapt] throws an exception.

    -?- Every function described in this section [rand.adapt] that has a function parameter q of type Sseq& for a template type parameter named Sseq that is different from type std::seed_seq throws what and when the invocation of q.generate throws.

Date: 2015-10-15.00:00:00

[ 2015-10-31, Daniel comments and simplifies suggested wording changes ]

Upon Walter Brown's suggestion the revised wording does not contain any wording changes that could be considered as editorial.

Previous resolution from Daniel [SUPERSEDED]:

This wording is relative to N3936.

  1. Edit the contents of sub-clause [rand.eng] as indicated:

    -1- Each type instantiated from a class template specified in this section [rand.eng] satisfies the requirements of a random number engine ([rand.req.eng]) type.

    -2- Except where specified otherwise, the complexity of each function specified in this section [rand.eng] is constant.

    -3- Except where specified otherwise, no function described in this section [rand.eng] throws an exception.

    -?- Every function described in this section [rand.eng] that has a function parameter q of type Sseq& for a template type parameter named Sseq that is different from type std::seed_seq throws what and when the invocation of q.generate throws.

    -4- Descriptions are provided in this section [rand.eng] only for engine operations that are not described in [rand.req.eng] or for operations where there is additional semantic information. In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality operators, and inequality operators are not shown in the synopses.

    -5- Each template specified in this section [rand.eng] requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold. A program instantiating any of these templates is ill-formed if any such required relationship fails to hold.

    -6- For every random number engine and for every random number engine adaptor X defined in this subclause ([rand.eng]) and in sub-clause [rand.adapt]:

    • if the constructor

      template <class Sseq> explicit X(Sseq& q);
      

      is called with a type Sseq that does not qualify as a seed sequence, then this constructor shall not participate in overload resolution;

    • if the member function

      template <class Sseq> void seed(Sseq& q);
      

      is called with a type Sseq that does not qualify as a seed sequence, then this function shall not participate in overload resolution;

    The extent to which an implementation determines that a type cannot be a seed sequence is unspecified, except that as a minimum a type shall not qualify as a seed sequence if it is implicitly convertible to X::result_type.

  2. Edit the contents of sub-clause [rand.adapt.general] as indicated:

    -1- Each type instantiated from a class template specified in this section [rand.eng][rand.adapt] satisfies the requirements of a random number engine adaptor ([rand.req.adapt]) type.

    -2- Except where specified otherwise, the complexity of each function specified in this section [rand.adapt] is constant.

    -3- Except where specified otherwise, no function described in this section [rand.adapt] throws an exception.

    -?- Every function described in this section [rand.adapt] that has a function parameter q of type Sseq& for a template type parameter named Sseq that is different from type std::seed_seq throws what and when the invocation of q.generate throws.

    -4- Descriptions are provided in this section [rand.adapt] only for adaptor operations that are not described in section [rand.req.adapt] or for operations where there is additional semantic information. In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality operators, and inequality operators are not shown in the synopses.

    -5- Each template specified in this section [rand.adapt] requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold. A program instantiating any of these templates is ill-formed if any such required relationship fails to hold.

  3. Edit the contents of sub-clause [rand.dist.general] p2 as indicated: [Drafting note: These editorial changes are just for consistency with those applied to [rand.eng] and [rand.adapt.general]end drafting note]

    -2- Descriptions are provided in this section [rand.dist] only for distribution operations that are not described in [rand.req.dist] or for operations where there is additional semantic information. In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality operators, and inequality operators are not shown in the synopses.

Date: 2014-05-15.00:00:00

[ 2014-05-22, Daniel syncs with recent WP ]

Date: 2015-05-22.19:14:31

[ Lenexa 2015-05-07: Move to Ready ]

LWG 2181 exceptions from seed sequence operations

STL: Daniel explained that I was confused. I said, oh, seed_seq says it can throw if the RanIt throws. Daniel says the RanIts are provided by the engine. Therefore if you give a seed_seq to an engine, it cannot throw, as implied by the current normative text. So what Daniel has in the PR is correct, if slightly unnecessary. It's okay to have explicitly non-overlapping Standardese even if overlapping would be okay.

Marshall: And this is a case where the std:: on seed_seq is a good thing.

STL: Meh.

STL: And that was my only concern with this PR. I like the latest PR much better than the previous.

Marshall: Yes. There's a drive-by fix for referencing the wrong section. Other than that, the two are the same.

STL: Alisdair wanted the repetition instead of centralization, and I agree.

Marshall: Any other opinions?

Jonathan: I'll buy it.

STL: For a dollar?

Hwrd: I'll buy that for a nickel.

Marshall: Any objections to Ready? I don't see a point in Immediate.

Jonathan: Absolutely agree.

Marshall: 7 for ready, 0 opposed, 0 abstain.

Date: 2014-02-15.00:00:00

[ 2014-02-09, Daniel provides alternative resolution ]

Date: 2013-04-15.00:00:00

[ 2013-04-20, Bristol ]

Remove the first bullet point:

?- Throughout this sub-clause general requirements and conventions are described that apply to every class template specified in sub-clause [rand.eng] and [rand.adapt]. Phrases of the form "in those sub-clauses" shall be interpreted as equivalent to "in sub-clauses [rand.eng] and [rand.adapt]".

Replace "in those sub-clauses" with "in sub-clauses [rand.eng] and [rand.adapt]".

Find another place for the wording.

Daniel: These are requirements on the implementation not on the types. I'm not comfortable in moving it to another place without double checking.

Improve the text (there are 4 "for"s): for copy constructors, for copy assignment operators, for streaming operators, and for equality and inequality operators are not shown in the synopses.

Move the information of this paragraph to the paragraphs it refers to:

"-?- Descriptions are provided in those sub-clauses only for engine operations that are not described in [rand.req.eng], for adaptor operations that are not described in [rand.req.adapt], or for operations where there is additional semantic information. In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality and inequality operators are not shown in the synopses."

Alisdair: I prefer duplication here than consolidation/reference to these paragraphs.

The room showed weakly favjust or for duplication.

Previous resolution from Daniel [SUPERSEDED]:

  1. Add a new sub-clause titled "Engine and engine adaptor class templates" following sub-clause [rand.synopsis] (but at the same level) and add one further sub-clause "General" as child of the new sub-clause as follows:

    Engine and engine adaptor class templates [rand.engadapt]

    General [rand.engadapt.general]

    -?- Throughout this sub-clause general requirements and conventions are described that apply to every class template specified in sub-clause [rand.eng] and [rand.adapt]. Phrases of the form "in those sub-clauses" shall be interpreted as equivalent to "in sub-clauses [rand.eng] and [rand.adapt]".

    -?- Except where specified otherwise, the complexity of each function specified in those sub-clauses is constant.

    -?- Except where specified otherwise, no function described in those sub-clauses throws an exception.

    -?- Every function described in those sub-clauses that has a function parameter q of type SSeq& for a template type parameter named SSeq that is different from type std::seed_seq throws what and when the invocation of q.generate throws.

    -?- Descriptions are provided in those sub-clauses only for engine operations that are not described in [rand.req.eng], for adaptor operations that are not described in [rand.req.adapt], or for operations where there is additional semantic information. In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality and inequality operators are not shown in the synopses.

    -?- Each template specified in those sub-clauses requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold. A program instantiating any of these templates is ill-formed if any such required relationship fails to hold.

    -?- For every random number engine and for every random number engine adaptor X defined in those sub-clauses:

    • if the constructor

      template <class Sseq> explicit X(Sseq& q);
      

      is called with a type Sseq that does not qualify as a seed sequence, then this constructor shall not participate in overload resolution;

    • if the member function

      template <class Sseq> void seed(Sseq& q);
      

      is called with a type Sseq that does not qualify as a seed sequence, then this function shall not participate in overload resolution;

    The extent to which an implementation determines that a type cannot be a seed sequence is unspecified, except that as a minimum a type shall not qualify as a seed sequence if it is implicitly convertible to X::result_type.

  2. Edit the contents of sub-clause [rand.eng] as indicated:

    -1- Each type instantiated from a class template specified in this section [rand.eng] satisfies the requirements of a random number engine ([rand.req.eng]) type and the general implementation requirements specified in sub-clause [rand.engadapt.general].

    -2- Except where specified otherwise, the complexity of each function specified in this section [rand.eng] is constant.

    -3- Except where specified otherwise, no function described in this section [rand.eng] throws an exception.

    -4- Descriptions are provided in this section [rand.eng] only for engine operations that are not described in [rand.req.eng] […]

    -5- Each template specified in this section [rand.eng] requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold. […]

    -6- For every random number engine and for every random number engine adaptor X defined in this subclause ([rand.eng]) and in sub-clause [rand.eng]: […]

  3. Edit the contents of sub-clause [rand.adapt.general] as indicated:

    -1- Each type instantiated from a class template specified in this section [rand.eng][rand.adapt] satisfies the requirements of a random number engine adaptor ([rand.req.adapt]) type and the general implementation requirements specified in sub-clause [rand.engadapt.general].

    -2- Except where specified otherwise, the complexity of each function specified in this section [rand.adapt] is constant.

    -3- Except where specified otherwise, no function described in this section [rand.adapt] throws an exception.

    -4- Descriptions are provided in this section [rand.adapt] only for engine operations that are not described in [rand.req.adapt] […]

    -5- Each template specified in this section [rand.adapt] requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold. […]

Date: 2012-08-19.16:32:07

LWG issue 2180 points out some deficiences in regard to the specification of the library-provided type std::seed_seq regarding exceptions, but there is another specification problem in regard to general types satisfying the seed sequence constraints (named SSeq) as described in [rand.req.seedseq].

[rand.eng] p3 and [rand.adapt.general] p3 say upfront:

Except where specified otherwise, no function described in this section [rand.eng]/[rand.adapt] throws an exception.

This constraint causes problems, because the described templates in these sub-clauses depend on operations of SSeq::generate() which is a function template, that depends both on operations provided by the implementor of SSeq (e.g. of std::seed_seq), and those of the random access iterator type provided by the caller. With class template linear_congruential_engine we have just one example for a user of SSeq::generate() via:

template<class Sseq> 
linear_congruential_engine<>::linear_congruential_engine(Sseq& q);

template<class Sseq> 
void linear_congruential_engine<>::seed(Sseq& q);

None of these operations has an exclusion rule for exceptions.

As described in 2180 the wording for std::seed_seq should and can be fixed to ensure that operations of seed_seq::generate() won't throw except from operations of the provided iterator range, but there is no corresponding "safety belt" for user-provided SSeq types, since [rand.req.seedseq] does not impose no-throw requirements onto operations of seed sequences.

  1. A quite radical step to fix this problem would be to impose general no-throw requirements on the expression q.generate(rb,re) from Table 115, but this is not as simple as it looks initially, because this function again depends on general types that are mutable random access iterators. Typically, we do not impose no-throw requirements on iterator operations and this would restrict general seed sequences where exceptions are not a problem. Furthermore, we do not impose comparable constraints for other expressions, like that of the expression g() in Table 116 for good reasons, e.g. random_device::operator() explicitly states when it throws exceptions.

  2. A less radical variant of the previous suggestion would be to add a normative requirement on the expression q.generate(rb,re) from Table 115 that says: "Throws nothing if operations of rb and re do not throw exceptions". Nevertheless we typically do not describe conditional Throws elements in proper requirement sets elsewhere (Container requirements excluded, they just describe the containers from Clause 23) and this may exclude resonable implementations of seed sequences that could throw exceptions under rare situations.

  3. The iterator arguments provided to SSeq::generate() for operations in templates of [rand.eng] and [rand.adapt] are under control of implementations, so we could impose stricter exceptions requirements on SSeq::generate() for SSeq types that are used to instantiate member templates in [rand.eng] and [rand.adapt] solely.

  4. We simply add extra wording to the introductive parts of [rand.eng] and [rand.adapt] that specify that operations of the engine (adaptor) templates that depend on a template parameter SSeq throw no exception unless SSeq::generate() throws an exception.

Given these options I would suggest to apply the variant described in the fourth bullet.

The proposed resolution attempts to reduce a lot of the redundancies of requirements in the introductory paragraphs of [rand.eng] and [rand.adapt] by introducing a new intermediate sub-clause "Engine and engine adaptor class templates" following sub-clause [rand.synopsis]. This approach also solves the problem that currently [rand.eng] also describes requirements that apply for [rand.adapt] (Constrained templates involving the Sseq parameters).

History
Date User Action Args
2017-07-30 20:15:43adminsetstatus: wp -> c++17
2016-06-28 12:47:21adminsetstatus: ready -> wp
2016-03-07 05:48:12adminsetstatus: review -> ready
2015-11-04 01:17:07adminsetstatus: ready -> review
2015-10-31 16:48:48adminsetmessages: + msg7594
2015-10-31 16:48:48adminsetstatus: review -> ready
2015-10-27 16:52:45adminsetstatus: ready -> review
2015-05-22 19:14:31adminsetmessages: + msg7434
2015-05-22 19:14:31adminsetstatus: open -> ready
2014-05-22 17:59:45adminsetmessages: + msg6964
2014-02-09 16:52:39adminsetmessages: + msg6810
2013-05-20 16:25:01adminsetmessages: + msg6508
2013-05-20 16:25:01adminsetstatus: new -> open
2012-08-19 12:58:58adminsetmessages: + msg6130
2012-08-18 00:00:00admincreate