libc++, std::bind, and <random>

Should the following work with clang and libc++?

#include <functional>
#include <random>

int main(int argc,char const *argv) {
    std::mt19937 re;
    std::normal_distribution<> di(30,8);
    auto rand = std::bind(di,re);
}

Clang outputs the following error for this program:

In file included from test.c++:2:
/usr/include/c++/v1/random:2234:9: error: no member named 'generate' in 'std::__1::mersenne_twister_engine<unsigned int, 32, 624, 397, 31, 2567483615, 11,
      4294967295, 7, 2636928640, 15, 4022730752, 18, 1812433253>'
    __q.generate(__ar, __ar + __n * __k);
    ~~~ ^

It looks to me like clang supports all the features necessary, and the code runs as expected in VS2010. Here's the command line I used:

clang++ -stdlib=libc++ -std=c++0x -U__STRICT_ANSI__ -pedantic -fno-blocks -frtti -g test.c++

I'm using revision 129268 of libc++ and clang -v outputs:

Should the following work with clang and libc++?

It certainly should.

#include <functional>
#include <random>

int main(int argc,char const *argv) {
   std::mt19937 re;
   std::normal_distribution<> di(30,8);
   auto rand = std::bind(di,re);
}

Clang outputs the following error for this program:

In file included from test.c++:2:
/usr/include/c++/v1/random:2234:9: error: no member named 'generate' in 'std::__1::mersenne_twister_engine<unsigned int, 32, 624, 397, 31, 2567483615, 11,
     4294967295, 7, 2636928640, 15, 4022730752, 18, 1812433253>'
   __q.generate(__ar, __ar + __n * __k);
   ~~~ ^

It's not clear to me why this is getting instantiated and with what
arguments. Can you post the full instantiation backtrace, i.e. all the
messages and not just the ultimate error?

John.

Here's the instantiation backtrace.

AMDG

Should the following work with clang and libc++?

#include<functional>
#include<random>

int main(int argc,char const *argv) {
     std::mt19937 re;
     std::normal_distribution<> di(30,8);
     auto rand = std::bind(di,re);
}

Clang outputs the following error for this program:

In file included from test.c++:2:
/usr/include/c++/v1/random:2234:9: error: no member named 'generate' in 'std::__1::mersenne_twister_engine<unsigned int, 32, 624, 397, 31, 2567483615, 11,
       4294967295, 7, 2636928640, 15, 4022730752, 18, 1812433253>'
     __q.generate(__ar, __ar + __n * __k);
     ~~~ ^

It looks to me like clang supports all the features necessary, and the code runs as expected in VS2010. Here's the command line I used:

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&);

In Christ,
Steven Watanabe

AMDG

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.

Howard

AMDG

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));

In Christ,
Steven Watanabe

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.

Howard

AMDG

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

Fix Committed revision 129285.

Thanks,
Howard