0

I have this following lines of code that the recent version of GCC cannot compile. I'm very sure it didn't even make a warning message.

seed_seq.cpp:

void func()
{
    std::mt19937_64 engine;
    std::hash<std::thread::id> hasher;
    uint64_t rdSeed, threadID, now;

    try
    {
        std::random_device rd;

        if (rd.entropy())
            rdSeed = rd();
        else
            rdSeed = 0;
    }
    catch (std::exception &)
    {
        rdSeed = 0;
    }

    threadID = hasher(std::this_thread::get_id());

    now = std::chrono::system_clock::now().time_since_epoch().count();

    engine.seed(std::seed_seq{ rdSeed, threadID, now });
}

Command: gcc -std=c++11 -c seed_seq.cpp -o seed_seq.o

GCC versions that can't compile:

  • gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1)
  • gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

VS2013 Update 5 doesn't complain. Definitely it's GCC's fault?

I do not remember the version of GCC that worked. Sorry.

Error:

seed_seq.cpp: In function ‘void func()’:
seed_seq.cpp:28:19: error: invalid initialization of non-const reference of type ‘std::seed_seq&’ from an rvalue of type ‘std::seed_seq’
  engine.seed(std::seed_seq{ rdSeed, threadID, now });
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/6.3.1/random:51:0,
                 from seed_seq.cpp:2:
/usr/include/c++/6.3.1/bits/random.tcc:353:7: note:   initializing argument 1 of ‘typename std::enable_if<std::is_class<_Sseq>::value>::type std::mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::seed(_Sseq&) [with _Sseq = std::seed_seq; _UIntType = long unsigned int; long unsigned int __w = 64ul; long unsigned int __n = 312ul; long unsigned int __m = 156ul; long unsigned int __r = 31ul; _UIntType __a = 13043109905998158313ul; long unsigned int __u = 29ul; _UIntType __d = 6148914691236517205ul; long unsigned int __s = 17ul; _UIntType __b = 8202884508482404352ul; long unsigned int __t = 37ul; _UIntType __c = 18444473444759240704ul; long unsigned int __l = 43ul; _UIntType __f = 6364136223846793005ul; typename std::enable_if<std::is_class<_Sseq>::value>::type = void]’
       mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d,
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          __s, __b, __t, __c, __l, __f>::
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Update

Found this on the system's dnf.log. Not sure which one is the one I used it on my project...

Nov 01 18:17:41 DEBUG ---> Package gcc-gdb-plugin.x86_64 6.2.1-2.fc24 will be installed
Nov 01 18:17:42 DEBUG ---> Package gcc.x86_64 5.3.1-6.fc23 will be upgraded
Nov 01 18:17:42 DEBUG ---> Package gcc.x86_64 6.2.1-2.fc24 will be an upgrade
Nov 01 18:17:42 DEBUG ---> Package gcc-c++.x86_64 5.3.1-6.fc23 will be upgraded
Nov 01 18:17:42 DEBUG ---> Package gcc-c++.x86_64 6.2.1-2.fc24 will be an upgrade
Nov 01 18:17:42 DEBUG ---> Package libgcc.x86_64 5.3.1-6.fc23 will be upgraded
Nov 01 18:17:42 DEBUG ---> Package libgcc.x86_64 6.2.1-2.fc24 will be an upgrade                                                  
Nov 02 11:03:25 DEBUG ---> Package gcc-debuginfo.x86_64 6.2.1-2.fc24 will be installed
Nov 02 11:03:25 DEBUG ---> Package gcc-base-debuginfo.x86_64 6.2.1-2.fc24 will be installed

Jan 04 09:59:34 DEBUG ---> Package gcc.x86_64 6.2.1-2.fc24 will be upgraded
Jan 04 09:59:34 DEBUG ---> Package gcc.x86_64 6.3.1-1.fc24 will be an upgrade
Jan 04 09:59:34 DEBUG ---> Package gcc-gdb-plugin.x86_64 6.2.1-2.fc24 will be upgraded
Jan 04 09:59:34 DEBUG ---> Package gcc-gdb-plugin.x86_64 6.3.1-1.fc24 will be an upgrade
Jan 04 09:59:34 DEBUG ---> Package gcc-c++.x86_64 6.2.1-2.fc24 will be upgraded
Jan 04 09:59:34 DEBUG ---> Package gcc-c++.x86_64 6.3.1-1.fc24 will be an upgrade
Jan 04 09:59:34 DEBUG ---> Package libgcc.x86_64 6.2.1-2.fc24 will be upgraded
Jan 04 09:59:34 DEBUG ---> Package libgcc.x86_64 6.3.1-1.fc24 will be an upgrade
  • Which gcc version is the obvious question here. And, have you used for example -Wall -pedantic when compiling? And which error is "kind" of important... What `engine.seed()` does? Here for example to generate 10 numbers starting from the sequence seq it uses the generate method http://en.cppreference.com/w/cpp/numeric/random/seed_seq – fedepad Feb 09 '17 at 08:23
  • Your code (with `this->__ctx->engine.seed(seq);` removed) compiles OK on GCC 6.1, 6.2, 6.3 and 7 (snapshot). https://godbolt.org/g/hU4Rz0 – simon Feb 09 '17 at 08:29
  • 'seed()' takes a reference, "something that potentially it can change". You're passing something that it cannot change. – fedepad Feb 09 '17 at 08:44
  • @fedepad It works when std::seed_seq is declared and passed to seed() as a variable. –  Feb 09 '17 at 08:50
  • Yes, or you do that, sure. As seen it here: http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/seed – fedepad Feb 09 '17 at 08:52
  • Well, I fixed and patched for this problem on my project. Problem solved. I just want GCC to be bug-free. And this is somewhat inconsistent with MSVC as well... MSVC is a bit better when it comes to implementing C++11 i guess. –  Feb 09 '17 at 08:54

1 Answers1

0

Clearly the parameter that you were passing to engine.seed() is the problem.
I suggest you to look at

seed()

Let's see briefly why.
As you can see there are two ways to call seed() defined by the followings:

void seed( result_type value = default_seed );

and

void seed( Sseq& seq );

If you're worried there's a bug in gcc, well I don't think you should.
Indeed Clang 3.9.1 (just to mention a version) gives a similar error too:

Start
prog.cc:32:12: error: no matching member function for call to 'seed'
    engine.seed(std::seed_seq{ rdSeed, threadID, now });
    ~~~~~~~^~~~
/opt/wandbox/clang-3.9.1/include/c++/v1/random:2116:10: note: candidate function not viable: no known conversion from 'std::seed_seq' to 'result_type' (aka 'unsigned long') for 1st argument
    void seed(result_type __sd = default_seed);
         ^
/opt/wandbox/clang-3.9.1/include/c++/v1/random:2124:9: note: candidate function [with _Sseq = std::__1::seed_seq] not viable: expects an l-value for 1st argument
        seed(_Sseq& __q)
        ^
1 error generated.
1
Finish

and points you exactly to the problem.
I find it very unlikely that both gcc and clang might have the same bug, but everything might be possible.
To see how you can call seed() in combination with std::seed_seq you should look at the following seed(), which has exactly a similar example.
The problem can be solved as you already mentioned either

std::seed_seq seq{ rdSeed, threadID, now };
engine.seed(seq);

or (which is way to verbose and I wouldn't do it probably):

std::seed_seq seq{ rdSeed, threadID, now };
std::seed_seq& pr = seq;
engine.seed(pr);

To read more about this kind of situation/kind of error, I suggest you to read the following SO post:
invalid initialization of non-const reference of type 'int&' from a temporary of type 'int'

As @Ashe the human pointed out in the comments, VS2013 let it compile because it's a language extension enabled by default: it is supposed to emit a warning to let people know. You can read more about it here:
Non-const reference bound to temporary, Visual Studio bug?

Community
  • 1
  • 1
fedepad
  • 4,509
  • 1
  • 13
  • 27
  • You didn't point out why VS2013 let it compile. It's a language extension enabled by default. Windows SDK can't be compiled without it. http://stackoverflow.com/questions/16380966/non-const-reference-bound-to-temporary-visual-studio-bug –  Feb 10 '17 at 01:02
  • oooooo Do I hate overpriced Microsoft products. –  Feb 10 '17 at 01:03
  • @Ashethehuman You're right! Sorry, but I do not have Windows so I didn't even look for it... I will include it in the answer! Good to know, interesting! – fedepad Feb 10 '17 at 07:49