Section: 29.5.3.2 [rand.req.seedseq] Status: NAD Submitter: Alberto Ganesh Barbati Opened: 2012-01-16 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [rand.req.seedseq].
View all issues with NAD status.
Discussion:
The seed sequence requirements described in 29.5.3.2 [rand.req.seedseq] appear to be over-specified.
All seed sequence types are required to have a result_type
nested type, a specific set of
constructors, function members size()
and param()
, which are never used by the library.
In fact, the only library components that actively use seed sequences are the random engines and all the
engines need is the generate()
member function. In particular, library components never attempts
to construct seed sequence objects. These extraneous requirements are clearly written to describe the
library provided type seed_seq
type; while it's good that seed_seq has all those constructors and
members, it's not a compelling reason to require a user-provided seed sequence type to implement all of
them.
class my_seed_seq { /* internals */ public: my_seed_seq(/* my own parameters */); template <class It> void generate(It first, It last); }; my_seed_seq s(/* params */); std::default_random_engine e(s);
The only reason to have these extra members would be to provide some support for generic serializability/persistence of seed sequence objects. I believe that would be out of the scope of the random library, so I doubt we will ever need those requirements in the future.
I therefore propose to remove all requirements from 29.5.3.2 [rand.req.seedseq] except for the presence of thegenerate()
function.
[2012, Kona]
Move to Tenatively NAD. (Tentative as issue was not in pre-meeting mailing)
The 'overspecification', as such, was a deliberate intent to provide guarantees consumers of the whole random number framework may rely upon, especially in generic code. While the standard engines may be built without relying on these guarantees, this specification is part of a commitment to a broader framework, and Walter indicated future proposals in preparation for parallel generation of random numbers that may depend more inimately on these existing requirements.
Alisdair noted that the result_type
typedef was a call-back to how we used to specify
adaptable functors before TR1 result_of
and the addition of std::bind
and is
probably not something we should be actively promoting in future libraries. However, it is too
late to remove this requirement from seed sequences unless we are doing further surgery, as
recommended by this issue.
Walter notes that the result_type
protocol has not been formally deprecated by the
standard. Alisdair replies that was the intent of deprecating the bind_1st
/
unary_function
set of templates in C++11, although we did not say anything about
result_type
in general.
Proposed resolution:
This wording is relative to the FDIS.
Edit 29.5.3.2 [rand.req.seedseq] p2 as indicated:
A class
S
satisfies the requirements of a seed sequence if the expressions shown in Table 115 are valid and have the indicated semantics, and ifS
also satisfies all other requirements of this section 29.5.3.2 [rand.req.seedseq]. In that Table and throughout this section:
T
is the type named byS
's associatedresult_type
;q
is a value ofS
and; andr
is a possibly const value ofS
ib
andie
are input iterators with an unsigned integervalue_type
of at least 32 bits;rb
andre
are mutable random access iterators with an unsigned integervalue_type
of at least 32 bits;ob
is an output iterator; andil
is a value ofinitializer_list<T>
.
Ditto, in Table 115, remove all rows except the one describing q.generate(rb, re)
:
Expression | Return type | Pre/Post-condition | Complexity |
---|---|---|---|
S::result_type |
T |
T is an unsigned integertype (6.8.2 [basic.fundamental]) of at least 32 bits. |
|
S() |
the same initial state as all other default-constructed seed sequences of type S . |
|
|
S(ib,ie) |
internal state that depends on some or all of the bits of the supplied sequence [ib, ie) . |
𝒪(ie - ib) |
|
S(il) |
S(il.begin(), . |
S(il.begin(), |
|
q.generate(rb,re)
|
void
|
Does nothing if rb == re .Otherwise, fills the supplied sequence [rb, re) with 32-bitquantities that depend on the sequence supplied to the constructor and possibly also depend on the history of generate 's previousinvocations. |
𝒪(re - rb)
|
r.size() |
size_t |
would be copied by a call to r.param . |
|
r.param(ob) |
void |
can be provided to the constructor of a second object of type S , and that wouldreproduce in that second object a state indistinguishable from the state of the first object. |
𝒪(r.size()) |