fail to capture random engine by value - c++11

I have this code that cannot be compiled by gcc 8, but I cannot understand why.
#include <iostream>
#include <algorithm>
#include <random>
using namespace std;
template<class... T>
void diagnose(T... x);
int main()
{
auto d = normal_distribution<double>(0.0, 1.0);
auto g = default_random_engine();
cout << d(g) << endl;
auto gen = [=](){
//diagnose(d, g);
return d(g); // ******
};
cout << gen() << endl;
}
The error message says (pointing to the line marked by *******):
error: no match for call to ‘(const std::normal_distribution<double>) (const std::linear_congruential_engine<long unsigned int, 16807, 0, 2147483647>&)
The code, however, works if I change the capture to be by reference.
If I uncomment the commented //diagnose line, the error message is like this (need also change return d(g) to return 1.0):
undefined reference to `void diagnose<std::normal_distribution<double>, std::linear_congruential_engine<unsigned long, 16807ul, 0ul, 2147483647ul> >(std::normal_distribution<double>, std::linear_congruential_engine<unsigned long, 16807ul, 0ul, 2147483647ul>)'
As you can see, in the capture-by-value case, the parameter g is a const reference. But the const does not appear in diagnosis.
Can somebody explain what is going on here?

You are passing d by value [=] so copy of this object is created inside lambda, but body of lambda function is const so you cannot change object inside lambda body. normal_distribution::operator() member is not-const. In const members you can invoke only const methods for member objects. You can resolve it by adding mutable to lambda
auto gen = [=]() mutable {
//diagnose(d, g);
return d(g); // ******
};
or passing d by reference
auto gen = [&](){
//diagnose(d, g);
return d(g); // ******
};

Related

auto reference to address in C++

I'm studying some C++ features, trying to play around with some experiments. However, I stuck in a place where it compiled error:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str = "some string";
auto &c = str.begin(); // compile error
*c = toupper(*c);
cout << *c << ", str: " << str << endl;
}
I'm not sure why it was not acceptable. My thought was that c had type char * (a pointer to a char), so that's why I had written as above. But why it failed in compiling?
Error C2440 Cannot transform 'std::_String_iteratorstd::_String_val<std::_Simple_types<_Elem>>' to'std::_String_iterator<std::_String_val<std::_Simple_types<_Elem
PS: Another method which I had tried first was OK.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str = "some string";
auto &c = *str.begin(); // success
c = toupper(c);
cout << c << ", str: " << str << endl;
}
begin() returns an iterator by value, not a reference. You are not allowed to form a non-const lvalue reference.
Making it const would prolong the life of the returned iterator and the program would then compile:
const auto &c = str.begin();
On the other hand, iterators are supposed to be cheap to copy and iterators from contiguous containers are often implemented as pure pointers. The idiomatic approach is:
auto c = str.begin();
In your second example, the idiomatic approach to form a reference to the first element would be:
auto& c = str.front();

Why reference_wrapper behaves differently for built-in types?

I have the following use of std::reference_wrapper for a build in type (double) and for a user defined type (std::string).
Why do they behave differently in the case of the stream operator?
#include<functional> //reference wrapper
#include<iostream>
void fd(double& d){}
void fs(std::string& s){}
int main(){
double D = 5.;
std::reference_wrapper<double> DR(D);
std::cout << "DR = " << DR << std::endl; //ok
fd(DR); // ok
std::string S = "hello";
std::reference_wrapper<std::string> SR(S);
std::cout << "SR = " << static_cast<std::string&>(SR) << std::endl; // ok
std::cout << "SR = " << SR << std::endl; // error: invalid operands to binary expression ('basic_ostream<char, std::char_traits<char> >' and 'std::reference_wrapper<std::string>')
fs(SR); // ok
}
http://coliru.stacked-crooked.com/a/fc4c614d6b7da690
Why in the first case DR is converted to double and printed and in the second it is not? Is there a work around?
Ok, I see now, in the ostream case I was trying to called a templated function that is not resolved:
#include<functional> //reference wrapper
void double_fun(double const& t){};
template<class C>
void string_fun(std::basic_string<C> const& t){};
int main(){
double D = 5.;
std::reference_wrapper<double> DR(D);
double_fun(DR); //ok
std::string S = "hello";
std::reference_wrapper<std::string> SR(S);
string_fun(SR); // error: no matching function for call to 'string_fun'
string_fun(SR.get()); // ok
string_fun(static_cast<std::string&>(SR)); // ok
string_fun(*&SR); // would be ok if `std::reference_wrapper` was designed/coded differently, see http://stackoverflow.com/a/34144470/225186
}
For the first part TC gave you the answer. That is, operator<< for basic_string is templated, and template argument deduction doesn't look through implicit conversions.
You could alternatively call SR.get() if you don't want to explicitly to static_cast your reference wrapper.
Now for the second part, string_fun takes as input arguments std::basic_string<C> objects. When you call:
string_fun(SR);
with SR as input parameter which is of type std::reference_wrapper<std::string>, naturally you get a type mismatch.
What you can do is provide an additional overload:
template<class C>
void string_fun(std::reference_wrapper<std::basic_string<C>> const& t) {
};
Live Demo
Or if you want a more unified treatment you could define your string_fun to take template template arguments, and resolve the type with some kind of type trait magic like bellow:
template<template<typename...> class C, typename T>
void
string_fun(C<T> const &t) {
std::cout <<
static_cast<std::conditional_t<
std::is_same<
std::reference_wrapper<T>, C<T>>::value, T, std::basic_string<T>>>(t) << std::endl;
}
Live Demo

Is this an example of reference reassignment? C++11

As I understand it, one cannot change the reference variable once it has been initialized. See, for instance, this question. However, here is a minmal working example which sort of does reassign it. What am I misunderstanding? Why does the example print both 42 and 43?
#include <iostream>
class T {
int x;
public:
T(int xx) : x(xx) {}
friend std::ostream &operator<<(std::ostream &dst, T &t) {
dst << t.x;
return dst;
}
};
int main() {
auto t = T(42);
auto q = T(43);
auto &ref = t;
std::cerr << ref << std::endl;
ref = q;
std::cerr << ref << std::endl;
return 0;
}
You're not changing the reference here.
You are replacing the object the reference is referring to.
In other words: after the assignment, your t is replaced by q.
ref is still a reference to t.
That does not perform a reference reassignment. Instead, it copy assigns the object in variable q into the object referenced by ref (which is t in your example).
This also justifies why you got 42 as output: the default copy assignment operator modified the first object.

How tu use a C++11 lambda asynchronously when capturing by reference

Can somebody explain the behavior of the following code?
When I explicitely convert my lambda to an std::function, the lambda correctly captures my variable n.
When it is implicitly converted to an std::function (using a temporary), then the capture fails.
I am using g++-4.9 (Ubuntu 4.9-20140406-1ubuntu1) 4.9.0 20140405 (experimental) [trunk revision 209157]
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>
std::shared_ptr<std::thread> call(const std::function<void()>& functor)
{
// Execute our functor asynchronously
return std::make_shared<std::thread>([&functor]
{
// Make sure all temporary are deallocated
std::this_thread::sleep_for(std::chrono::seconds(1));
// Execute our functor
functor();
});
}
int main()
{
int n{};
std::cout << "in main " << &n << std::endl;
// -> in main 0x7fffd4e1a96c
auto lambda = [&n]
{
std::cout << "in lambda " << &n << std::endl;
};
// Here we do an explicit convertion to std::function
std::cout << "explicit convertion" << std::endl;
auto function = std::function<void()>{ lambda };
auto pThreadFunction = call(function);
pThreadFunction->join();
// -> in lambda 0x7fffd4e1a96c
// Here we use an implicit convertion to std::function
std::cout << "implicit convertion" << std::endl;
auto pThreadLambda = call(lambda);
pThreadLambda->join();
// -> in lambda 0
return 0;
}
The lifetime of a temporary constructed for binding to a const reference function parameter is the full-expression containing that function call, so your thread function is referring to a dangling reference.
You should only capture variables into a thread function by reference if you can guarantee that the lifetime of the variable contains the lifetime of the thread, as you have done in the case where function is a local variable in main.
One alternative would be to call join within the full-expression that constructs the temporary:
call(lambda)->join();
Another more general solution would be to capture functor by value in your thread function.

Strange behaviour of passing out refernce in binding of lambda function

I want to pass out some parameter from the lambda function, so I bind a reference parameter to a lambda function. However, the outer variable is not changed after calling the function. If I bind the lambda function with the pointer of outer variable, the result is correct.
I show the test program as follows and want to know why the outer variable does not change, given that I have already defined the pass-by-reference lambda function [&]?
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
int main(int argc, char* argv[])
{
string acc_ref, acc_ptr;
// define function via reference
auto fProcRefEx = [&](string& acc, const string& s) -> void
{
acc += s;
};
auto fProcRef = bind(fProcRefEx, acc_ref, placeholders::_1);
// define function via pointer
auto fProcPtrEx = [&](string* pacc, const string& s) -> void
{
(*pacc) += s;
};
auto fProcPtr = bind(fProcPtrEx, &acc_ptr, placeholders::_1);
// test
vector<string> v = {"abc", "def"};
for_each(v.begin(), v.end(), fProcRef);
cout << "acc_ref: " << acc_ref << endl; // acc_ref is empty, wrong
for_each(v.begin(), v.end(), fProcPtr);
cout << "acc_ptr: " << acc_ptr << endl; // acc_ptr is "abcdef", correct
return 0;
}
I think std::bind will decay the reference to just a plain value type when it stores acc_ref. ie In the unspecified object instance returned from bind, it will have a member string acc_ref, not string& acc_ref. You have to use std::ref to make it really store a reference:
auto fProcRef = bind(fProcRefEx, ref(acc_ref), placeholders::_1);

Resources