I have a functor that creates a linearly spaced set of values . . .
//Linear spaced generator
struct gen_lin {
float mi, inc;
public:
gen_lin(float _mi=1.f, float _inc=1.f) : mi(_mi), inc(_inc){};
float operator()() {
return mi+=inc;
}
};
And I can fill a vector with values like so ...
const size_t elements = 400;
std::vector<float> x(elements);
std::generate_n(x.begin(), elements, gen_lin(10.f,5.f) );
Now, I can easily convert this to a log scale using a lambda like so ...
auto lin = gen_lin(10.f,5.f);
std::generate_n(x.begin(), elements, [&](){return logf(lin());} );
But when I try to squeeze it all on to one line, the vector is entirely filled with the value of logf(10.)
std::generate_n(x.begin(), elements, [](){return logf( gen_lin(10.f,5.f)() );} );
Why, and is it possible to tweak my last line of code to make it work?
With this, you are creating a single gen_lin object, and using it multiple times:
auto lin = gen_lin(10.f,5.f);
std::generate_n(x.begin(), elements, [&](){return logf(lin());} );
With this, you are creating several gen_lin objects:
std::generate_n(x.begin(), elements, [](){return logf( gen_lin(10.f,5.f)() );} );
Each time you create a new gen_lin object, the current value gets reset.
In the first case:
auto lin = gen_lin(10.f,5.f);
std::generate_n(x.begin(), elements, [&](){return logf(lin());} );
You have a persistent gen_lin object, lin, that gets updated with every call to the lambda. But with your one-liner, you are just creating fresh gen_lin object with every call to the lambda, getting the first value that it returns, and then throwing the object away. Since it's a fresh object, initialized with the same constant values, it's going to give you the same value every time.
Each lamdas call creates a new instance of your functor in the second case.
Stuff like bind might fix your problem. Make the lambda take your functor as an argument and use bind to attach a common instance to that argument?
Or use a compose functor of whatever flavour.
Related
This is my code:
HelloApplication::HelloApplication(const Wt::WEnvironment& env)
: Wt::WApplication(env)
{
setTitle("Data Interpolation");
Wt::WText *InitialExplanation = root()->addWidget(std::make_unique<Wt::WText>());
InitialExplanation->setText("Welcome! This is a page that will allow you to interpolate the value at a point in the domain of your dataset, using other points in your dataset.\n I used Lagrange Interpolation for this calculation.\n Created By Vashist Hegde");
root()->addWidget(std::make_unique<Wt::WBreak>());
std::vector<double> xi;
std::vector<double> yi;
std::vector<double> xMissing;
double xM;
auto addDataPoint = [this,xi,yi,lineEdit1,lineEdit2] () mutable{
/// neither of the following push_backs is working.
/// I get 2 empty vectors in the end.
xi.push_back(std::move(std::stod(lineEdit1->text())));
yi.push_back(std::move(std::stod(lineEdit2->text())));
xi.push_back(3.5);
yi.push_back(4.5);
};
I don't get any errors but when I run the program, the vectors are just not getting populated. I get 0 sized vectors.
Is this related to my general C++ usage or is it related to Wt (C++ Web toolkit)?
If it is related to the general C++ usage, please help me as to what I'm doing wrong.
Your lambda should capture the variable by ref which has to be to be modified, otherwise the changes will be done to the copy of the captured things.
Additionally, you need to invoke lambda for get in action.
auto addDataPoint = [this,&xi,&yi,lineEdit1,lineEdit2] () mutable {
// ...... do something
};
addDataPoint(); // call lambda
alternatively pass them as ref qualified arguments
auto addDataPoint = [this, lineEdit1,lineEdit2]
(auto& xi_para, auto &yi_para,) mutable {
// ...... do something
};
addDataPoint(xi, yi); // call lambda with args
````
Assume that I have a functionality which I want to call whenever a timer finishes. I have put that piece of functionality in a lambda function. Furthermore, in that function, I may wish to set another timer to call that same lambda on another, later occasion.
void doSetupThingsInSomeDecoupledCodeOrWhatever() {
std::function<void(float)> semiRecursiveFunc;
semiRecursiveFunc = [&semiRecursiveFunc](float deltaT){
if (whatever()) {
// Do something...
}
else {
// Do something else, then:
float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f)
// Gives the timer a duration to wait, and a function to run at the end of it.
getTimerSystem().setNewTimer(durationMS, semiRecursiveFunc);
}
};
float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f)
// Gives the timer a duration to wait, and a function to run at the end of it.
getTimerSystem().setNewTimer(durationMS, fooLambda);
}
Now, clearly this won't work, because semiRecursiveFunc is tied to the scope of doSetupThingsInSomeDecoupledCodeOrWhatever, and when the timer system tries to run it the function will no longer exist and everything will disintegrate into a spectacular ball of flame.
What's the best way to manage this? I can't store semiRecursiveFunc in a pointer because one can't declare lambdas like that, as far as I can tell. Is there some common tool for this sort of persistent-lambda use-case? What's the least ugly approach, with minimum surrounding infrastructure? Is there a best-practice to follow, some relevant tool I've missed? Any suggestions or recommendations would be much appreciated.
What you're looking for is a y-combinator, sometimes called a fixed-point combinator.
Either way, instead of using std::function at all (which adds needless overhead), you would write your callback like this:
auto semiRecursiveCallback = combinator([](auto self, float deltaT){
if (whatever()) {
// Do something...
}
else {
// Do something else, then:
float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f)
// Gives the timer a duration to wait, and a function to run at the end of it.
// NB: we pass 'self' as the argument
getTimerSystem().setNewTimer(durationMS, self);
}
});
Where combinator is either the y_combinator implementation of my linked answer or boost::hof::fix from the excellent Boost.HOF library.
The combinator ensures that the object itself has access to itself, so you can do recursive things. In the above code, you're actually getting passed a copy of yourself, but that's fine: value semantics are cool like that.
Here is a tiny Y-combinator:
template<class R>
auto Y = [] (auto f) {
auto action = [=] (auto action) {
return [=] (auto&&... args)->R {
return f( action(action),decltype(args)(args)... );
};
};
return action(action);
};
Just do this:
auto semiRecursiveFunc = Y<void>([](auto&& semiRecursiveFunc, float deltaT){
if (whatever()) {
// Do something...
}
else {
// Do something else, then:
float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f)
// Gives the timer a duration to wait, and a function to run at the end of it.
getTimerSystem().setNewTimer(durationMS, semiRecursiveFunc);
}
);
and it works.
Y<R> takes a callable that is passed what to recurse on as its first argument. When you recurse, just pass the rest of the arguments.
You can write a fancier Y combinator. This one copies the lambdas state a lot and isn't picky about moving it, to keep its implementation simple. It also requires you provide its return type (that is harder to avoid, due to C++ type deduction rules).
Here's a way that is in the style of Objective-C reference counting. The advantage is that you can use a lambda signature that is the same as the original function you want (no extra arguments). The disadvantages are that it looks ugly and verbose, and you have to always use the lambda through a shared_ptr; you can't take it out and pass it separately.
void doSetupThingsInSomeDecoupledCodeOrWhatever() {
std::shared_ptr<std::weak_ptr<std::function<void(float)>>> weakFuncHolder =
std::make_shared<std::weak_ptr<std::function<void(float)>>>();
std::shared_ptr<std::function<void(float)>> semiRecursiveFunc =
std::make_shared<std::function<void(float)>>([=](float deltaT) {
std::shared_ptr<std::function<void(float)>> strongFunc(*weakFuncHolder);
if (whatever()) {
// Do something...
}
else {
// Do something else, then:
float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f);
// Gives the timer a duration to wait, and a function to run at the end of it.
getTimerSystem().setNewTimer(durationMS,
[=](float deltaT){ (*strongFunc)(deltaT); });
}
});
*weakFuncHolder = semiRecursiveFunc;
float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f);
// Gives the timer a duration to wait, and a function to run at the end of it.
getTimerSystem().setNewTimer(durationMS,
[=](float deltaT){ (*semiRecursiveFunc)(deltaT); });
}
I have a dream. That I can store lambda expressions passed to a function in a vector as objects wrapped in a class.
These are then run at a given point later and if their have a return value, it is obtained.
I've been trying find a way to do this, e.g. my other post hit a standstill Vector with objects that have function pointers of varying type
The reason I want it this way is so that it is as dynamic and easy to use in any scenario as possible.
In the current case, it's to be used in evolutionary algorithms that perform tasks across separate processes and memory spaces.
Is my dream unfeasible, or bad design? Do you know a better way? I've been at this for days without having anything that compiles.
I'd be grateful to be pointed in the right direction.
Basically something along these lines:
std::vector<CallbackJob> myCallbackList;
std::vector<CallbackJobResult> myCallbackResultList;
Callback myCB = make_callback( [&]{ return Task->Test("I return boolean"); } );
Callback myCB2 = make_callback( [&]{ return Foo("I return doubles"); } );
CallbackJob job1("name1", myCB, 1);
CallbackJob job2("name2", myCB2, 5);
myCallbackList.push_back(job1);
myCallbackList.push_back(job2);
for(auto &i : myCallbackList) {
// maybe need to check if it has a return value, embed it into the callback object itself?
myCallbackResultList.push_back( i.callback() );
}
You can use type erasure, for instance std::any and std::function, to store lambdas and their resulting values in vectors:
std::vector<std::function<std::any()>> functions;
functions.emplace_back([]{ return std::any(1.0); });
functions.emplace_back([]{ return std::any(true); });
std::vector<std::any> results;
for (auto & f : functions)
results.emplace_back(f());
The question is how to process the elements of results, since you need to know their types to cast them with std::any_cast. In this example, you can use, e.g.:
for (const auto & r : results)
if (r.type() == typeid(double))
std::cout << std::any_cast<double>(r);
else if (r.type() == typeid(bool))
std::cout << std::any_cast<bool>(r);
Also note that this will work only if all lambdas have either no parameters or, eventually, parameters of the same type.
I need to use a tuple in my code to be able to conveniently store three data with different type in a vector. That is to say, I have something like this :
std::vector<std::tuple<sf::Time, sf::Time, std::function<void()> > > m_timedFunctions;
Where the first sf::Time represent how often should we call the std::function, and the second sf::Time represent the timestamp of the last call to the function. The goal is to be able to call a function at regular interval automatically.
I have no problem creating and inserting a tuple into the vector, but for some reason when I try to modify the second sf::Time using std::get<1>(u), it just does not happen. I can read the data perfectly, but in no way it lets me modify it.
Here's how I create the tuple :
void addTimedFunction(sf::Time freq, std::function<void()> f)
{
auto a = std::make_tuple(freq, sf::seconds(0), f);
m_timedFunctions.push_back(a);
}
but later if I do something like this : std::get<1>(a) = sf::seconds(10); (where a is a tuple from m_timedFunctions that I get with a ranged-base for), the second member stays at 0.
The whole part of my code where I'm modifying it :
void MainWindow::processTimedFunctions()
{
for(auto a : m_timedFunction)
{
sf::Time elapsed = m_clock.getElapsedTime();
sf::Time lastExec = std::get<1>(a);
sf::Time diff = elapsed - lastExec;
if( diff.asMilliseconds() >= std::get<0>(a).asMilliseconds())
{
std::get<1>(a) = sf::seconds(10); // m_clock.getElapsedTime(); // Update the last execution time
std::get<2>(a)(); // Call the linked function
}
}
}
How can I effectively modify it ?
This creates a copy of the elements you're iterating over:
for(auto a : m_timedFunction)
Any changes you make to a will not affect the container.
To get a reference instead of a copy, use:
for(auto &a : m_timedFunction)
I'm new to C++ and I'm trying to make a little game. I have this class named "UnitController" which stores multiple instances of the class "Unit" in a map. The class also has a method "getUnit" which should return one of the stored units.
It seems this method is only partially working. I think I get a copy of the unit instead of the requested instance.
Could anyone point me int the right direction?
#include "UnitController.h"
#include "Unit.h"
using namespace ci;
using std::map;
UnitController::UnitController()
{
}
void UnitController::addUnit( Vec2f position )
{
Unit mUnit = Unit();
mUnit.setup( position );
Units.insert( std::pair<int,Unit>( Units.size()+1, mUnit ) );
}
Unit UnitController::getUnit( int k )
{
Unit selectedUnit = Units[0];
return selectedUnit;
}
void UnitController::update()
{
for( map<int,Unit>::iterator u = Units.begin(); u != Units.end(); ++u ){
u->second.update();
}
}
void UnitController::draw()
{
for( map<int,Unit>::iterator u = Units.begin(); u != Units.end(); ++u ){
u->second.draw();
}
}
The method:
Unit UnitController::getUnit( int k )
{
Unit selectedUnit = Units[0];
return selectedUnit;
}
is returning a, possibly default, copy of the element with index 0 (do you mean to ignore k?). If you wish to avoid a copy being returned then return a reference instead to the element at index 0, not to the local variable selectedUnit:
Unit& UnitController::getUnit( int k )
{
return Units[k];
}
If the entry keyed by k is removed from the map then a caller that has a reference to the Unit of the entry now has a dangling reference, use of which is undefined behaviour. There a few things to consider to try and avoid this:
Does a client of UnitController require direct access to a Unit in the map? If not and the client only requires to update certain attributes of a Unit then modify the UnitController interface to support updates to Unit without providing a client direct access.
If a client does require direct access then consider using a std::shared_ptr<Unit> instead of a Unit for entry value type (and don't return by reference in this case). This would address the dangling reference problem but what does it mean for caller to have access to a Unit that is no longer in the UnitController?
operator[] will create an entry in the map for a key that does not currently exist:
Inserts a new element to the container using key as the key and a default constructed mapped value and returns a reference to the newly constructed mapped value. If an element with key key already exists, no insertion is performed and a reference to its mapped value is returned.
If you wish to not have this behaviour then use find() and decide on what action to take if an entry for key k does not exist.
In this code:
Unit UnitController::getUnit( int k )
{
Unit selectedUnit = Units[0];
return selectedUnit;
}
you return Unit by value, so you actually get a copy of the original Unit.
(Note also that you seem to have a bug, since you use 0 as key, instead of parameter k...)
If you want to modify the original Unit (i.e. the one stored in the map), you can return by reference (Unit &):
Unit& UnitController::getUnit(int key)
{
return Units[k];
}
As a side note, you can simplify your insertion code. Instead of using std::map::insert() method:
Units.insert( std::pair<int,Unit>( Units.size()+1, mUnit ) );
you can just use std::map::operator[] overload:
Units[ ...the key here... ] = mUnit;
You will indeed receive a deep copy of Unit.
Consider creating a reference counting pointer (aka smart pointer) encapsulating a Unit and set that to the value type of the map.
of course you get the copy. consider this:
void UnitController::addUnit( Vec2f position )
{
Unit mUnit = Unit(); // you create local instance of Unit
mUnit.setup( position );
// you add it to the map - actually the copy is created and stored in map
Units.insert( std::pair<int,Unit>( Units.size()+1, mUnit ) );
// mUnit is destroyed after the function exits
// your map would now contain a destroyed object if it wasn't a copy
}
Besides your getUnit method also returns a copy. this might be OK or not, depending on what the client does with it. if it changes the state of returned unit instance, then it will not be reflected in the copies withing the map.
You might want to use map<int,Unit*> but then you need to take care of lifetime of the original objects. You can't destroy it because pointer will point to destroyed object. Therefore, a proper solution is to use shared_ptr<Unit>
However, there are other problems with your design. You store the current size + 1 as the map key, which means that you use it as an index. Why not just use std::vector<shared_ptr<Unit>> instead?