Can I declare a variable inside a lambda capture clause? - c++

I want to submit a handle but I only want it to be executed if a shared pointer is still valid:
// elsewhere in the class:
std::shared_ptr<int> node;
// later on:
const std::weak_ptr<int> slave(node); // can I do this in the capture clause somehow?
const auto hook = [=]()
{
if (!slave.expired())
//do something
else
// do nothing; the class has been destroyed!
};
someService.Submit(hook); // this will be called later, and we don't know whether the class will still be alive
Can I declare slave within the capture clause of the lambda? Something like const auto hook = [std::weak_ptr<int> slave = node,=]().... but unfortunately this doesn't work. I would like to avoid declaring the variable and then copying it (not for performance reasons; I just think it would be clearer and neater if I could create whatever the lambda needs without polluting the enclosing scope).

You can do this using generalized lambda captures in C++14:
const auto hook = [=, slave = std::weak_ptr<int>(node)]()
{
...
};
Here's a live example. Note that since there are no parameters or explicit return type, the empty parameter list (()) can be left out.

As mentioned by chris this is possible in C++14.
If you are willing to modify the captured value simply add mutablespecifier.
Here is an example which fills a vector from zero to the length of the vector.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> container(10);
std::generate(container.begin(), container.end(), [n = 0]() mutable { return n++; });
for (const auto & number : container)
{
std::cout << number << " ";
}
std::cin.ignore();
return 0;
}

Related

C++ lambda capture only const references [duplicate]

Is it possible to capture by const reference in a lambda expression?
I want the assignment marked below to fail, for example:
#include <algorithm>
#include <string>
using namespace std;
int main()
{
string strings[] =
{
"hello",
"world"
};
static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);
string best_string = "foo";
for_each( &strings[0], &strings[num_strings], [&best_string](const string& s)
{
best_string = s; // this should fail
}
);
return 0;
}
Update: As this is an old question, it might be good to update it if there are facilities in C++14 to help with this. Do the extensions in C++14 allow us to capture a non-const object by const reference? (August 2015)
In c++14 using static_cast / const_cast:
[&best_string = static_cast<const std::string&>(best_string)](const string& s)
{
best_string = s; // fails
};
DEMO
In c++17 using std::as_const:
[&best_string = std::as_const(best_string)](const string& s)
{
best_string = s; // fails
};
DEMO 2
const isn't in the grammar for captures as of n3092:
capture:
identifier
& identifier
this
The text only mention capture-by-copy and capture-by-reference and doesn't mention any sort of const-ness.
Feels like an oversight to me, but I haven't followed the standardization process very closely.
I think the capture part should not specify const, as the capture means, it only need a way to access the outer scope variable.
The specifier is better specified in the outer scope.
const string better_string = "XXX";
[&better_string](string s) {
better_string = s; // error: read-only area.
}
lambda function is const(can't change value in its scope), so when you capture variable by value, the variable can not be changed, but the reference is not in the lambda scope.
There is a shorter way.
Note that there is no ampersand before "best_string".
It will be of a const std::reference_wrapper<T> type.
[best_string = std::cref(best_string)](const string& s)
{
best_string = s; // fails
};
http://coliru.stacked-crooked.com/a/0e54d6f9441e6867
I guess if you're not using the variable as a parameter of the functor, then you should use the access level of the current function. If you think you shouldn't, then separate your lambda from this function, it's not part of it.
Anyway, you can easily achieve the same thing that you want by using another const reference instead :
#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string strings[] =
{
"hello",
"world"
};
static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);
string best_string = "foo";
const string& string_processed = best_string;
for_each( &strings[0], &strings[num_strings], [&string_processed] (const string& s) -> void
{
string_processed = s; // this should fail
}
);
return 0;
}
But that's the same as assuming that your lambda have to be isolated from the current function, making it a non-lambda.
I think you have three different options:
don't use const reference, but use a copy capture
ignore the fact that it is modifiable
use std::bind to bind one argument of a binary function which has a const reference.
using a copy
The interesting part about lambdas with copy captures is that those are actually read only and therefore do exactly what you want them to.
int main() {
int a = 5;
[a](){ a = 7; }(); // Compiler error!
}
using std::bind
std::bind reduces the arity of a function. Note however that this might/will lead to an indirect function call via a function pointer.
int main() {
int a = 5;
std::function<int ()> f2 = std::bind( [](const int &a){return a;}, a);
}
Use clang or wait until this gcc bug is fixed:
bug 70385: Lambda capture by reference of const reference fails [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70385]
Using a const will simply have the algorithm ampersand set the string to it's original value,
In other words, the lambda won't really define itself as parameter of the function, though the surrounding scope will have an extra variable...
Without defining it though, it wouldn't define the string as the typical
[&, &best_string](string const s)
Therefore, its most likely better if we just leave it at that, trying to capture the reference.

Hold a collection of member function pointers and decorated member function pointers

As a part of a much larger project, one of my objects (Thing in MWE) has a set of filters (filterStrong, filterWeak) defined on it. The goal is to use all the implemented filters in complexFilteringProcedure, where the user could chose the filtering rule through a parameter, and the function itself would depend on the success of the filtering rule chosen. The function complexFilteringProcedure would act on an object of type Thing, and call one of its private methods (filtering rules) depending on the parameter.
I implemented this by holding a vector of all possible filters in filteringOptions and implementing a single public filtering interface, filterUsingRule. Ideally, this would allow me to later on add new filtering rules to the project as I need them, and only modify the setFilteringFunction where the filter list is initialized.
Now, I started writing a new set of filtering rules, and realized all of them could be obtained by decorating the current filtering rules all in the same manner (softenFilter; please do correct me if "decorating" is the wrong expression here). I remembered reading into std::bind recently and taught, great. I would also like to add all the decorated filtering rules in my list of filteringOptions, that is, every original filter decorated with softenFilter.
Reading up a little bit more on std::bind, I think the possible reasons for my problems are twofold:
the return type of std::bind is a templated mess, and definitely not Thing::filteringFunction
I might be binding the this referring to the calling object when defining softStrong and softWeak
But, I am stuck further than that, not sure how to look for a solution to my specific problem. My main question are: Can this functionality be achieved? (functionality of filterUsingRule) and further, Can this functionality be achieved elegantly? (I know I could always define a set of functions bool softStrong(int param) { return softenFilter(filterStrong, param); } that manually bind the filters to the decorator, but I was hoping that std::bind or some new C++ magic would help with that).
The MWE recreating what I have successfully done and what I would like to achieve is as follows:
#include <iostream>
#include <vector>
#include <functional>
class Thing{
private:
int basicFilter;
typedef bool (Thing::*filteringFunction)(int);
static std::vector<filteringFunction> filteringOptions;
bool filterStrong(int parameter) {return parameter > basicFilter*2;}
bool filterWeak(int parameter) {return parameter > basicFilter;}
bool softenFilter(filteringFunction f, int parameter){
if (!((this->*(f))(parameter)))
return (this->*(f))(parameter+2);
return true;
}
void setFilteringFunctions(void){
Thing::filteringOptions.emplace_back(&Thing::filterStrong);
Thing::filteringOptions.emplace_back(&Thing::filterWeak);
auto softStrong = std::bind(&Thing::softenFilter,
&Thing::filterStrong,
std::placeholders::_1); // ok
auto softWeak = std::bind(&Thing::softenFilter,
&Thing::filterWeak,
std::placeholders::_1); // ok
filteringOptions.emplace_back(&softStrong); // how?
filteringOptions.emplace_back(softWeak); // how?
}
public:
Thing(int basicFilter) : basicFilter(basicFilter){
if (Thing::filteringOptions.empty())
setFilteringFunctions();
}
bool filterUsingRule(int parameter, int rule = 0){
return ((int)Thing::filteringOptions.size() > rule) &&
(this->*(Thing::filteringOptions[rule]))(parameter);
}
};
std::vector <Thing::filteringFunction> Thing::filteringOptions(0);
void complexFilteringProcedure(Thing &aThing, int parameter, int rule){
// do a lot of things
if (aThing.filterUsingRule(parameter, rule))
std::cout << "Filtering with " << rule << "successful" << std::endl;
else
std::cout << "Filtering with " << rule << "failed" << std::endl;
// and some more things
}
int main(void){
Thing myThing(5), otherThing(10);
complexFilteringProcedure(myThing, 7, 0); // uses strong rule
complexFilteringProcedure(otherThing, 7, 1); // uses weak rule
complexFilteringProcedure(myThing, 7, 2); // how to do this correctly?
complexFilteringProcedure(otherThing, 7, 3); // or this?
}
You might use std::function
using filteringFunction = std::function<bool (Thing&, int)>;
and then
void setFilteringFunctions()
{
Thing::filteringOptions.emplace_back(&Thing::filterStrong);
Thing::filteringOptions.emplace_back(&Thing::filterWeak);
auto softStrong = std::bind(&Thing::softenFilter,
std::placeholders::_1,
&Thing::filterStrong,
std::placeholders::_2
);
auto softWeak = std::bind(&Thing::softenFilter,
std::placeholders::_1,
&Thing::filterWeak,
std::placeholders::_2);
Thing::filteringOptions.emplace_back(&softStrong);
Thing::filteringOptions.emplace_back(&softWeak);
// or
Thing::filteringOptions.emplace_back([](Thing& instance, int param){
return instance.filterStrong(param + 2) });
}
You'll have to use a specialization of std::function as your vector element type. The key issue is that the object returned by std::bind() is not a bare function pointer. It is rather a Callable -- a function object -- it is some type (exactly what type is unimportant and in fact unspecified) that has an operator() with the appropriate return type which takes the appropriate parameters. This is exactly the role of std::function -- a type which can wrap any Callable of the correct signature in a way that lets you handle it with a known concrete type regardless of the actual type of the Callable.
typedef std::function<bool(int)> filteringFunction;
static std::vector<filteringFunction> filteringOptions;
// now can you store your member function pointers in
// filteringOptions after bind()ing the first parameter
// as you've already done
To satisfy the skeptics, here is the OP's code modified to use this technique.
#include <iostream>
#include <vector>
#include <functional>
class Thing{
private:
int basicFilter;
typedef std::function<bool(int)> filteringFunction;
static std::vector<filteringFunction> filteringOptions;
bool filterStrong(int parameter) {return parameter > basicFilter*2;}
bool filterWeak(int parameter) {return parameter > basicFilter;}
bool softenFilter(filteringFunction f, int parameter){
if (!f(parameter))
return f(parameter + 2);
return true;
}
void setFilteringFunctions(void){
filteringFunction strong = std::bind(&Thing::filterStrong,
this, std::placeholders::_1);
filteringFunction weak = std::bind(&Thing::filterWeak,
this, std::placeholders::_1);
filteringFunction softStrong = std::bind(&Thing::softenFilter,
this, strong, std::placeholders::_1);
filteringFunction softWeak = std::bind(&Thing::softenFilter,
this, weak, std::placeholders::_1);
filteringOptions.emplace_back(softStrong);
filteringOptions.emplace_back(softWeak);
}
public:
Thing(int basicFilter) : basicFilter(basicFilter){
if (Thing::filteringOptions.empty())
setFilteringFunctions();
}
bool filterUsingRule(int parameter, int rule = 0){
return ((int)Thing::filteringOptions.size() > rule) &&
filteringOptions[rule](parameter);
}
};
std::vector <Thing::filteringFunction> Thing::filteringOptions(0);
void complexFilteringProcedure(Thing &aThing, int parameter, int rule){
// do a lot of things
std::cout << "Filtering: " << aThing.filterUsingRule(parameter, rule) << std::endl;
// and some more things
}
int main(void){
Thing myThing(5), otherThing(10);
complexFilteringProcedure(myThing, 7, 0); // uses strong rule
complexFilteringProcedure(otherThing, 7, 1); // uses weak rule
//complexFilteringProcedure(myThing, 7, 2); // how to use soft strong rule?
//complexFilteringProcedure(otherThing, 7, 3); // how to use soft weak rule?
}
typedef std::function<bool(Thing*, int)> filteringFuction;
Now you can use static functions as well as std::bind and lambda or any callable that accepts an int and returns bool.
static bool test(Thing*, int);
static bool decoratee(Thing*, bool , int);
this->filteringOptions.emplace_back([](Thing* sth, int x){return false;});
this->filteringOptions.emplace_back(&Thing::weakFilter);
this->filteringOptions.emplace_back(std::bind(decoratee, _1, false, _2));
this->filteringOptions.emplace_back(&test);
int param;
for(auto& callee:this->filteringOptions)
callee(this,param);

Is there a way of writing this shorter without capturing lambda variables?

I'm not sure if anyone else ever makes a temporary with a shorter name when it'll be used in many lines of code, for example you need to access something a couple of classes deep and instead of chaining member access operators over and over you'll just use a shorter named temporary. I tried doing something like the following:
struct Car
{
struct
{
struct
{
int height, width, depth;
} physicalInfo;
} information;
} objectWithARatherLongName ;
int main()
{
auto lambda1 = [] { return objectWithARatherLongName.information.physicalInfo.height; };
// Create a temporary for a shorter name
auto& dimens = objectWithARatherLongName.information.physicalInfo;
auto lambda2 = [=] { return dimens.height; };
// Have to capture "dimens" because it's a local variable
// And over and over again, the shorter way is preferred.
}
In this case auto dimens is the short named temporary, but since I want to use it in the lambda I need to capture it, which made me made think I should just use the full name that is a global. Is there a way to shorten this in the way I described but still be using the global variable? I thought about a typedef that will only work with types right? Not with actual objects.
Don't use global variables, but if you must you probably can add one more:
struct Car
{
...
} objectWithARatherLongName ;
auto& dimens = objectWithARatherLongName.information.physicalInfo;
int main() { // ...

Lambda: A by-reference capture that could dangle

Scott Meyers, in Effective Modern C++, says, at lambda chapter, that:
Consider the following code:
void addDivisorFilter()
{
auto calc1 = computeSomeValue1();
auto calc2 = computeSomeValue2();
auto divisor = computeDivisor(calc1, calc2);
filters.emplace_back(
[&](int value) { return value % divisor == 0; }
);
}
This code is a problem waiting to happen. The lambda refers to the local variable divisor, but that variable ceases to exist when addDivisorFilter returns. That's immediately after filters.emplace_back returns, so the function that's added to filters is essentially dead on arrival. Using that filter yields undefined behaviour from virtually the moment it's created.
The question is: Why is it an undefined behaviour? For what I understand, filters.emplace_back only returns after lambda expression is complete, and, during it execution, divisor is valid.
Update
An important data that I've missed to include is:
using FilterContainer = std::vector<std::function<bool(int)>>;
FilterContainer filters;
That's because the scope of the vector filters outlives the one of the function. At function exit, the vector filters still exists, and the captured reference to divisor is now dangling.
For what I understand, filters.emplace_back only returns after lambda expression is complete, and, during it execution, divisor is valid.
That's not true. The vector stores the lambda created from the closure, and does not "execute" the lambda, you execute the lambda after the function exits. Technically the lambda is constructed from a closure (an compiler-dependent-named class) that uses a reference internally, like
#include <vector>
#include <functional>
struct _AnonymousClosure
{
int& _divisor; // this is what the lambda captures
bool operator()(int value) { return value % _divisor == 0; }
};
int main()
{
std::vector<std::function<bool(int)>> filters;
// local scope
{
int divisor = 42;
filters.emplace_back(_AnonymousClosure{divisor});
}
// UB here when using filters, as the reference to divisor dangle
}
You are not evaluating the lambda function while addDivisorFilter is active. You are simply adding "the function" to the collection, not knowing when it might be evaluated (possibly long after addDivisorFilter returned).
In addition to #vsoftco's answer, the following modified example code lets you experience the problem:
#include <iostream>
#include <functional>
#include <vector>
void addDivisorFilter(std::vector<std::function<int(int)>>& filters)
{
int divisor = 5;
filters.emplace_back(
[&](int value) { return value % divisor == 0; }
);
}
int main()
{
std::vector<std::function<int(int)>> filters;
addDivisorFilter(filters);
std::cout << std::boolalpha << filters[0](10) << std::endl;
return 0;
}
live example
This example results in a Floating point exception at runtime, since the reference to divisor is not valid when the lambda is evaluated in main.

Why can't I create a vector of lambdas (of the same type) in C++11?

I was trying to create a vector of lambda, but failed:
auto ignore = [&]() { return 10; }; //1
std::vector<decltype(ignore)> v; //2
v.push_back([&]() { return 100; }); //3
Up to line #2, it compiles fine. But the line#3 gives compilation error:
error: no matching function for call to 'std::vector<main()::<lambda()>>::push_back(main()::<lambda()>)'
I don't want a vector of function pointers or vector of function objects. However, vector of function objects which encapsulate real lambda expressions, would work for me. Is this possible?
Every lambda has a different type—even if they have the same signature. You must use a run-time encapsulating container such as std::function if you want to do something like that.
e.g.:
std::vector<std::function<int()>> functors;
functors.push_back([&] { return 100; });
functors.push_back([&] { return 10; });
All lambda expressions have a different type, even if they are identical character-by-character. You're pushing a lambda of a different type (because it's another expression) into the vector, and that obviously won't work.
One solution is to make a vector of std::function<int()> instead.
auto ignore = [&]() { return 10; };
std::vector<std::function<int()>> v;
v.push_back(ignore);
v.push_back([&]() { return 100; });
On another note, it's not a good idea to use [&] when you're not capturing anything.
While what others have said is relevant, it is still possible to declare and use a vector of lambda, although it's not very useful:
auto lambda = [] { return 10; };
std::vector<decltype(lambda)> vec;
vec.push_back(lambda);
So, you can store any number of lambdas in there, so long as it's a copy/move of lambda!
If your lambda is stateless, i.e., [](...){...}, C++11 allows it to degrade into a function pointer. In theory, a C++11 compliant compiler would be able to compile this:
auto ignore = []() { return 10; }; //1 note misssing & in []!
std::vector<int (*)()> v; //2
v.push_back([]() { return 100; }); //3
You could use a lambda generating function (updated with fix suggested by Nawaz):
#include <vector>
#include <iostream>
int main() {
auto lambda_gen = [] (int i) {return [i](int x){ return i*x;};} ;
using my_lambda = decltype(lambda_gen(1));
std::vector<my_lambda> vec;
for(int i = 0; i < 10; i++) vec.push_back(lambda_gen(i));
int i = 0;
for (auto& lambda : vec){
std::cout << lambda(i) << std::endl;
i++;
}
}
But I think you basically made your own class at this point. Otherwise if the lambdas have completely different caputres/args etc. you probably have to use a tuple.
Each lambda is a different type. You must use std::tuple instead of std::vector.