I have been reading Lambda capture as const reference?
It is an interesting feature, and sometimes I also wish this feature to exist, especially when I have huge data, which I need to access inside a lambda function.
My follow up questions -
Should we capture by const reference in lambda? If yes, how should it be behave?
(Edit - I am also interested in the behaviour of the lifetime of the captured variable.)
Is there any possible downside, by introducing it in the C++ grammar? (I can't think of any)
Let us assume we can.
We assume [const &] as syntax to capture.
int x = 10;
auto lambda = [const & x](){ std::cout << x << std::endl; };
lambda(); // prints 10, great, as expected
x = 11;
lambda(); // should it print 11 or 10 ?
My intuition is that is should behave just like [&] but the captured value should not be allowed to modify.
template<typename Func>
void higher_order_function(int & x, Func f)
{
f(); // should print 11
x = 12;
f(); // should print 12
}
void foo()
{
int x = 10;
auto c = [const & x] () { std::cout << x << std::endl; };
c(); // should print 10
x = 11;
c(); // should print 11
higher_order_function(x, c);
auto d = [const & x] () { x = 13; }; // Compiler ERROR: Tried to assign to const qualified type 'const int &'!
}
I've been wondering about this myself.
Since the operator() is const by default, I would assume that allowing const references is acceptable as well.
With the current standards(C++17), the closest I got to this behaviour is:
auto c = [ &x = std::as_const(x) ] () { std::cout << x << std::endl; };
Workaround in C++11/C++14 would be(thanks to Daniel for suggestion):
auto const & crx = x;
auto c = [ &crx ] () { std::cout << crx << std::endl; };
lambda(); // should it print 11 or 10 ?
I don't understand why it should print 10. Consider lambda being just an instance of some anonymous class. Making it a normal class, it should look like:
class Lambda {
public:
Lambda(const int & i) : i_(i) { }
void operator()() { std::cout << i_ << std::endl; }
private:
const int & i_;
};
int x = 10;
Lambda lambda(x);
lambda(); // prints 10, great, as expected
x = 11;
lambda(); // should it print 11 or 10 ?
The meaning of const reference here is only that you cannot modify x through i_ member reference variable.
A simlpler scenario:
int x = 10;
const int & crx = x;
x++;
std::cout << crx << std::endl; // prints 11
Maybe not exactly what you're looking for but... I suppose you can pass through a function that receive the same value by const reference.
Something as follows
template <typename T>
auto make_capture_const (T const & x)
{ return [&x](){ std::cout << x << std::endl; }; }
// ...
int x { 42 };
auto l = make_capture_const(x);
l();
If you try to modify x inside the lambda
std::cout << x++ << std::endl;
you should get an error.
As you can see, from, this solution you get that x can't be modified inside the lambda but the lambda is influenced from the value changes outside
int x { 42 };
auto l = make_capture_const(x);
l(); // print 42
x = 43;
l(); // print 43
IMHO, an hypothetic [const &] capture syntax should works in the same way. But I understand that is highly questionable.
Related
Thank you all, I didn't even know about user-defined conversion function and how it works.
Why is it possible to use std::reference_wrapper<int>::operator+=, if such an operator does not exist, are there some implicit conversions?
#include <iostream>
#include <functional>
#include <boost/type_index.hpp>
using boost::typeindex::type_id_with_cvr;
template <typename C>
void test(C c)
{
c += 1;
}
int main()
{
int a = 3;
test(a);
std::cout << a << std::endl;
test(std::ref(a));
std::cout << a << std::endl;
}
Output:
3
4
To check that template works perfectly fine:
void test_2(std::reference_wrapper<int> c)
{
c += 1;
}
int main()
{
int a = 3;
test_2(std::ref(a));
std::cout << a << std::endl;
}
Output:
4
Still works as before. How is that possible?
Funny thing, that in auto d = b + c, d has an integer type.
int main()
{
auto b = std::ref(a);
auto c = std::ref(a);
auto d = b + c;
std::cout << type_id_with_cvr<decltype(d)>).pretty_name() << std::endl;
}
Output:
int
It's because it's implicitly convertible to a reference to T:
/* constexpr [c++20] */ operator T& () const noexcept;
In your case, it's implicitly convertible to an int&.
This ability to be implicitly convertible to an int& is also what would make it possible for you to define your function to take an int& while passing it a std::reference_wrapper<int>:
void test_2(int& c) // <--+
{ // |
c += 1; // |
} // |
int main() { // |
// ... // |
test_2(std::ref(a)); // >--+
}
This question already has answers here:
What is the difference between prefix and postfix operators?
(13 answers)
Closed 5 years ago.
I come across this problem accidentally.
I have thought google can solve it surely, but after searching multiple keywords, I still can't find answers, which confused me a lot.
When I use prefix at tail position, codes works fine:
template<class ContinerIterator, class F>
constexpr auto fun(ContinerIterator IteratorBegin, ContinerIterator IteratorEnd, F f)
{
switch (IteratorBegin == IteratorEnd)
{
case true: return;
case false: f(*IteratorBegin);
}
return fun(++IteratorBegin, IteratorEnd, f);
}
int main()
{
std::vector<int> a = { 1, 2, 3, 4 };
fun(std::begin(a), std::end(a), [](auto &a)->auto{a *= 2; });
for (auto v : a)
{
std::cout << v << std::endl;
}
return 0;
}
1
2
3
4
Press any key to continue . . .
Howerer, if I use postfix, IteratorBegin nerve arrives iteratorEnd and goes far and far away, so segmentfault.
template<class ContinerIterator, class F>
constexpr auto fun(ContinerIterator IteratorBegin, ContinerIterator IteratorEnd, F f)
{
switch (IteratorBegin == IteratorEnd)
{
case true: return;
case false: f(*IteratorBegin);
}
return fun(IteratorBegin++, IteratorEnd, f);
}
void test()
{
}
int main()
{
std::vector<int> a = { 1, 2, 3, 4 };
fun(std::begin(a), std::end(a), [](auto &a)->auto{a *= 2; });
for (auto v : a)
{
std::cout << v << std::endl;
}
return 0;
}
I have tried on MSVC, G++, Clang, all fails.
Here is gcc's error list:
Segmentation fault (core dumped)
Here is Clang's:
Error occurred (timeout). Try again later.
This statement
return fun(IteratorBegin++, IteratorEnd, f);
with some exceptions can be considered like
fun(IteratorBegin, IteratorEnd, f);
++IteratorBegin;
return;
So the function is always called with the same value of IteratorBegin.
From the C++ Standard (5.2.6 Increment and decrement)
1 The value of a postfix ++ expression is the value of its operand. [
Note: the value obtained is a copy of the original value —end note
]...
Consider the following simple program
#include <iostream>
void f(int x)
{
std::cout << "Inside f( x ): x = " << x << std::endl;
}
int main()
{
int x = 0;
std::cout << "Before f( x ): x = " << x << std::endl;
f(x++);
std::cout << "After f( x ): x = " << x << std::endl;
return 0;
}
Its output is
Before f( x ): x = 0
Inside f( x ): x = 0
After f( x ): x = 1
Also it will be useful to consider the following simple program
#include <iostream>
int x = 0;
void f(int x)
{
std::cout << "Local (parameter) x = " << x << std::endl;
std::cout << "Global variable ::x = " << ::x << std::endl;
}
int main()
{
f(x++);
return 0;
}
Its output is
Local (parameter) x = 0
Global variable ::x = 1
The prefix case:
return fun(++IteratorBegin, IteratorEnd, f);
says, first increment IteratorBegin by one, and then call the function fun. After that, return.
On the other hand, the postfix case:
return fun(IteratorBegin++, IteratorEnd, f);
says, first call fun(), then increment the iterator, and then return.
This means that fun() is always being called with the non-incremented iterator.
When you use postfix increment in the tail call, the recursive call does not get the incremented value of the iterator. It gets the value of the iterator before the increment is applied. Hence, the recursion is infinite. That causes stack overflow.
#include <iostream>
typedef std::function<bool(int)> set;
using namespace std;
set singletonSet(int a) {
return [&] (int x) { return (a == x); };
}
bool contains(set s, int test) {
return s(test);
}
int main() {
auto first = singletonSet(5);
auto r1 = contains(first, 10);
auto r2 = contains(first, 5);
cout << r1 << " " << r2 << endl;
return 0;
}
I expect this to print 0 1 but result is 1 1
Beginner c++ labmda programmer here so sorry in advance if this is a basic error.
Don't capture a by reference, capture it by value. As-is, you're storing a dangling reference inside the lambda, and using it later leads to UB.
set singletonSet(int a) {
return [=] (int x) { return (a == x); };
// ^
}
I have studied auto and I know it deduces types from initialized values. If I tried to write some guidelines for usage of auto, can I put below statements as rules?
Use auto && for all values (r-values and l-value, as it is an universal ref) that are modifiable,
auto && even for read only values,
Use auto wherever possible (individual preference for coding style).
EDIT
class Test
{
public:
Test() = default;
Test(const Test&) = default;
Test(Test&&) = default;
int i = 1;
};
Test getObj()
{
return Test();
}
Test& getObjByRef()
{
static Test tobj;
return tobj;
}
const Test getObjConst()
{
return Test();
}
int main()
{
auto && obj1 = getObj();
obj1.i = 2;
std::cout << " getObj returns: " << getObj().i << std::endl;
auto&& obj2 = getObjByRef();
obj2.i = 3;
std::cout << " getObjByRef returns: " << getObjByRef().i << std::endl;
auto && obj3 = getObjConst();
//obj3.i = 4; => //Error C3490 'i' cannot be modified because it is being accessed through a const object
return 0;
}
So in above example i used auto && for all three functions
getObj
getObjByRef
getObjConst
and it works as expected.
Now can I conclude that:
auto && can be used to hold(initialize) any value, OR
We can use auto && every possible place.
Do you see any pitfall of this approach?
1) Yes
2) Yes
3) As you said, 'individual preference for coding style'
Creating a functor requires an unnecessary boiler plate. The state has to be written 4 times!
struct f{
double s; // 1st
f(double state): s(state) {} // 2nd, 3rd and 4th
double operator() (double x) {
return x*s;
}
};
is there a library with a macro that would be just double functor(state)(x){ return x*state; } or something similar.
BOOST_FOREACH is a macro adapter that works well. I'm looking for something similar.
any suggestions on how to write one is appreciated too.
ps. using struct for functor is faster then bind Class's operator() or bind a function as a functor?
Update(1)
in regards to lambdas:
the functor has to be modular, meaning, it should be reusable in other function. lambdas have to be within a function -- lambda has to be in main to be called from main and other functions outside of main, can't call the lambda defined in main.
How about relying on aggregate initialization? Simply do not declare the constructor:
struct f {
double s;
double operator()(double x) {
return x * s;
}
};
use it like this
int main()
{
auto ff = f{42};
std::cout << ff(2);
return 0;
}
Define the functionality you want, e.g., you multiplication, as a function and then use std::bind() to create a suitable function object:
#include <functional>
double some_operation(double state, double x) {
return state * x;
}
int main() {
auto function = std::bind(&some_operation, 17, std::placeholders::_1);
return function(18);
}
Since a call through a function pointer generally can't be inlined, you might want to write your function as a function object instead:
#include <functional>
struct some_operation {
double operator()(double state, double x) const {
return state * x;
}
};
int main() {
auto function = std::bind(some_operation(), 17, std::placeholders::_1);
return function(18);
}
Below is a test program which seems to indicate that the speed of a hand-crafted function object and a bound function object are about the same, i.e., the results I get are
in 90 ms, functor as a struct; result = 1.5708e+16
in 262 ms, function pointer through bind; result = 1.5708e+16
in 261 ms, function through bind; result = 1.5708e+16
in 87 ms, function object through bind; result = 1.5708e+16
in 88 ms, non-called bind with function; result = 1.5708e+16
in 88 ms, non-called bind with function pointer; result = 1.5708e+16
using a recent version of clang (more precisely: clang version 3.4 (trunk 182411)) on a MacOS system optimizing with -O2 option. Using and gcc (more precisely: gcc version 4.9.0 20130811 (experimental) (GCC)) gives similar results.
It seems it makes a difference whether the function object is build in the local context or passed via template argument to a separate function. This difference is interesting as I would expect that most of the uses of bind() a function will result in passing off the resulting function object somewhere.
The code is based on https://stackoverflow.com/a/18175033/1120273:
#include <iostream>
#include <functional>
#include <chrono>
using namespace std;
using namespace std::placeholders;
using namespace std::chrono;
struct fs {
double s;
fs(double state) : s(state) {}
double operator()(double x) {
return x*s;
}
};
struct ff {
double operator()(double x, double state) const {
return x * state;
}
};
double fb(double x, double state) {
return x*state;
}
template <typename Function>
void measure(char const* what, Function function)
{
const auto stp1 = high_resolution_clock::now();
double sresult(0.0);
for(double x=0.0; x< 1.0e8; ++x) {
sresult += function(x);
}
const auto stp2 = high_resolution_clock::now();
const auto sd = duration_cast<milliseconds>(stp2 - stp1);
cout << "in " << sd.count() << " ms, ";
cout << what << "; result = " << sresult << endl;
}
int main() {
double state=3.1415926;
measure("functor as a struct", fs(state));
measure("function through bind", std::bind(&fb, _1, state));
measure("function object through bind", std::bind(ff(), _1, state));
{
const auto stp1 = high_resolution_clock::now();
double sresult(0.0);
auto function = std::bind(fb, _1, state);
for(double x=0.0; x< 1.0e8; ++x) {
sresult += function(x);
}
const auto stp2 = high_resolution_clock::now();
const auto sd = duration_cast<milliseconds>(stp2 - stp1);
cout << "in " << sd.count() << " ms, ";
cout << "embedded bind with function; result = " << sresult << endl;
}
{
const auto stp1 = high_resolution_clock::now();
double sresult(0.0);
auto function = std::bind(&fb, _1, state);
for(double x=0.0; x< 1.0e8; ++x) {
sresult += function(x);
}
const auto stp2 = high_resolution_clock::now();
const auto sd = duration_cast<milliseconds>(stp2 - stp1);
cout << "in " << sd.count() << " ms, ";
cout << "embedded bind with function pointer; result = " << sresult << endl;
}
return 0;
}
We've got lambdas for this:
double s = 42;
auto f = [s](double x) {
return s * x;
};
Down to single mention of state on line 2 (as you dont seem to count one in the actual expression). Whether initialization on line 1 counts as mention is debatable, your desired form does not contain any initialization, which is required, so I assume this to be acceptable.
In c++14 we'll get extension of lambda capture syntax allowing even more terse form:
auto f = [s{42}](double x) {
return s * x;
};
Have a look at BOOST_LOCAL_FUNCTION which seems to be exactly what youre looking for, as you even mention a macro :)
double s = 42;
double BOOST_LOCAL_FUNCTION(bind& s, double x) {
return x*s;
} BOOST_LOCAL_FUNCTION_NAME(f)
Personal note: If you have a modern compiler, go with C++11 lambdas.