[cfe-dev] libc++, std::bind, and <random>

Howard Hinnant hhinnant at apple.com
Mon Apr 11 10:47:35 PDT 2011


On Apr 11, 2011, at 12:38 PM, Howard Hinnant wrote:

> On Apr 11, 2011, at 12:22 PM, Steven Watanabe wrote:
> 
>> AMDG
>> 
>> On 04/11/2011 08:38 AM, Howard Hinnant wrote:
>>> 
>>> On Apr 11, 2011, at 11:30 AM, Steven Watanabe wrote:
>>> 
>>>> When calling the copy constructor of a Random
>>>> Number Engine with a non-const argument, the library is
>>>> incorrectly treating the argument as a SeedSeq.
>>>> The two declarations in question are:
>>>> 
>>>> mersenne_twister(const mersenne_twister&);
>>>> template<typename SeedSeq>  mersenne_twister(SeedSeq&);
>>> 
>>> Thanks Steven.  I'm working on an improved constraint
>>> for the SeedSeq template parameter.  The current
>>> constraint is simply that it is not implicitly
>>> convertible to the engine's result_type.
>>> 
>> 
>> I think that constraint is wrong.  (I don't have
>> the final draft, so my information could be
>> out of date, however. I'm referencing n3242)
>> 
>> Here are the relevant sections:
>> a) T is the type named by E's associated result_type;
>> c) s is a value of T;
>> d) q is an lvalue satisfying the requirements of
>>   a seed sequence (26.5.1.2);
>> 
>> Table 117 -- Random number engine requirements
>> E(s) -- Creates an engine with initial state determined by s.
>> E(q) -- Creates an engine with an initial state that
>>        depends on a sequence produced by one call
>>        to q.generate.
>> 
>> Now consider the following class:
>> 
>> class my_seed_seq
>> {
>> public:
>>    ...all members required for a seed sequence...
>>    operator bool() const;
>> };
>> 
>> According to the above,
>> 
>>  my_seed_seq q;
>>  std::mt19937 gen(q);
>> 
>> should call the seed sequence constructor.
>> If you use a convertible constraint, it will
>> be equivalent to
>> 
>>  std::mt19937 gen(bool(q));
> 
> I'm in search of a seed sequence constraint that clang will compile without -std=c++0x.  Suggestions welcome.  What I'm doing at the moment:
> 
> I've created a new trait:
> 
> template <class _Sseq, class _Engine>
> struct __is_seed_sequence;
> 
> to replace each place in <random> where I'm currently using !isconvertible.  That will make fixing this bug easier.  My current definition is:
> 
> template <class _Sseq, class _Engine>
> struct __is_seed_sequence
> {
>    static const bool value =
>              !is_convertible<_Sseq, typename _Engine::result_type>::value &&
>              !is_same<typename remove_cv<_Sseq>::type, _Engine>::value;
> };
> 
> That passes Seth's test, but fails yours.
> 
> Ideally I'd like to test for the generate member of the seed sequence (with C++03 mode turned on).  But as that member function may take random access iterators that may take an infinite number of forms, I'm currently lacking a test to detect the member generate.
> 
> Suggestions welcome.

I should have added that I expect the following test to  pass:

    int seed = 5;
    std::mt19937 re3(seed);

which is the motivation for the part of the constraint that Sseq is not implicitly convertible to Engine::result_type.  I would also expect the Engine to be seedable with a BigInt class which has an implicit conversion to Engine::result_type.

Oh, one more thing.  26.5.3 [rand.eng]/6 ends with:

> 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.


Howard




More information about the cfe-dev mailing list