c++ - Why does creating a temporary instance not work in this case? -


i've been learning c++11 through bjarne stroustrup's "a tour of c++".

i have following snippet of code

#include <random> #include <functional>  int main(int argc, char *argv[]) {     using namespace std;     std::default_random_engine generator;     std::uniform_int_distribution<int> distribution {1,6};     distribution(generator); //case 1 works      auto die = bind(uniform_int_distribution<>{1,6},default_random_engine{});  //case 2 works      distribution(std::default_random_engine{});     //case 3 compiler error  } 

case 3 own creation while case 2 comes book , case 1 adapted elsewhere. why case 3 produce compiler error below? far understand, difference between case 1 , case 3 i'm using temporary instance of std::default_random_engine , temporary instance seems work in case 2 missing?

error output:

random.cpp: in function ‘int main(int, char**)’: random.cpp:13:46: error: no match call ‘(std::uniform_int_distribution<int>) (std::default_random_engine)’      distribution(std::default_random_engine{});     //case 3 compiler error                                               ^ in file included /usr/include/c++/6.3.1/bits/random.h:35:0,                  /usr/include/c++/6.3.1/random:49,                  random.cpp:1: /usr/include/c++/6.3.1/bits/uniform_int_dist.h:164:2: note: candidate: std::uniform_int_distribution<_inttype>::result_type std::uniform_int_distribution<_inttype>::operator()(_uniformrandomnumbergenerator&) [with _uniformrandomnumbergenerator = std::linear_congruential_engine<long unsigned int, 16807ul, 0ul, 2147483647ul>; _inttype = int; std::uniform_int_distribution<_inttype>::result_type = int] <near match>   operator()(_uniformrandomnumbergenerator& __urng)   ^~~~~~~~ /usr/include/c++/6.3.1/bits/uniform_int_dist.h:164:2: note:   conversion of argument 1 ill-formed: random.cpp:13:23: error: invalid initialization of non-const reference of type ‘std::linear_congruential_engine<long unsigned int, 16807ul, 0ul, 2147483647ul>&’ rvalue of type ‘std::default_random_engine {aka std::linear_congruential_engine<long unsigned int, 16807ul, 0ul, 2147483647ul>}’      distribution(std::default_random_engine{});     //case 3 compiler error                        ^~~~~~~~~~~~~~~~~~~~~~~ in file included /usr/include/c++/6.3.1/bits/random.h:35:0,                  /usr/include/c++/6.3.1/random:49,                  random.cpp:1: /usr/include/c++/6.3.1/bits/uniform_int_dist.h:169:2: note: candidate: template<class _uniformrandomnumbergenerator> std::uniform_int_distribution<_inttype>::result_type std::uniform_int_distribution<_inttype>::operator()(_uniformrandomnumbergenerator&, const std::uniform_int_distribution<_inttype>::param_type&) [with _uniformrandomnumbergenerator = _uniformrandomnumbergenerator; _inttype = int]   operator()(_uniformrandomnumbergenerator& __urng,   ^~~~~~~~ /usr/include/c++/6.3.1/bits/uniform_int_dist.h:169:2: note:   template argument deduction/substitution failed: random.cpp:13:46: note:   candidate expects 2 arguments, 1 provided      distribution(std::default_random_engine{});     //case 3 compiler error                                               ^ 

distribution(generator); 

distribution modifies state of generator, , extracts value. on next call, returns different value, using same generator

auto die = bind(uniform_int_distribution<>{1,6},default_random_engine{}); 

here, copy both uniform_int_distribution<>{1,6} , default_random_engine{} bind function object. on () passes default_random_engine{} uniform_int_distribution<>{1,6} via operator(). uniform_int_distribution<>{1,6} modifies state of default_random_engine{} , on next call, returns different value, uses (now modified) generator.

distribution(std::default_random_engine{}); 

here attempt bind random_engine& temporary object. distribution wants modify random engine's state, why taken reference.

by passing in temporary, such change discarded instantly. easy accidentally , screw up, c++ default not let bind temporary object non-const lvalue reference.

the designers of c++ std wanted error, took distribution non-const lvalue reference. trying tell "this bad plan".

you can work around it:

template<class t> t& as_lvalue(t&& t){ return t; } 

now

distribution(as_lvalue(std::default_random_engine{})); 

fools compiler thinking default_random_engine passed in not temporary. still goes away @ end of line , modification state of generator, done distribution, discarded.

this not want when generating pseudo-random objects, c++11's random engine about.

in short, not permitted bind temporaries non-constant lvalue references. when so, error. when have parameter intended both read , written to, , written value important, taken non-constant lvalue reference, in order prevent casually passing in temporary , having data written lost.

generators stateful. want keep 1 around , repeatedly apply distribution it.


Comments

Popular posts from this blog

Command prompt result in label. Python 2.7 -

javascript - How do I use URL parameters to change link href on page? -

amazon web services - AWS Route53 Trying To Get Site To Resolve To www -