callback vs lambda - c++

Suppose I have the following code that I wish to refactor:
int toFuture()
{
precalc();
int calc = 5 * foobar_x() + 3;
postcalc();
return calc;
}
int toPast()
{
precalc();
int calc = 5 * foobar_y() - 9;
postcalc();
return calc;
}
In classic-C, I would refactor this code into a worker() which accepts a function pointer that does the calculation: common code in worker(), specific code provided by function pointer.
With C++11, should I be using a lambda instead? If so, how would I implement it, in this case?
Edit: it just crossed my mind that a template may also work. How would a template implementation compare against the other two?

One approach:
template<typename CalcFuncT>
int perform_calc(CalcFuncT&& calcfunc)
{
precalc();
int const calc = std::forward<CalcFuncT>(calcfunc)();
postcalc();
return calc;
}
int main()
{
perform_calc([]{ return 5 * foobar_x() + 3; }); // toFuture
perform_calc([]{ return 5 * foobar_y() - 9; }); // toPast
}

If you are wanting a template approach using C++11 features, that could look as simple as:
template<typename FuncType>
auto calculation(FuncType&& func) -> decltype(func())
{
precalc();
auto ret = func();
postcalc();
return ret;
}
You would then simply call your calculation function and pass it either a lambda, a functor, or a function-pointer. Your only souce of difficulty in this instance would be if you passed a function that had a void return-type ... in that case you will get a compiler error (which is a good thing vs. a runtime error).

I'd say you're refactoring from the wrong side:
struct CalcGuard {
CalcGuard() { /* replaces precalc() */ }
~CalcGuard() { /* replaces postcalc() */ }
};
int toFuture()
{
return CalcGuard(), calc = 5 * foobar_x() + 3;
}
int toPast()
{
return CalcGuard(), calc = 5 * foobar_y() - 9;
}

There is a C/C++ way to do this, and a C++11 way. Neither way involves lambdas or templates.
The C/C++ way:
double MyFunc (int x, float y) { return x + y ; }
int main()
{
double (*pf) (int, float) ;
pf = MyFunc ;
pf (101, 202.0) ;
}
The C++11 way:
#include <functional>
double MyFunc (int x, float y) { return x + y ; }
int main()
{
std::function<double (int, float)> f ;
f = MyFunc ;
f (51, 52.0) ;
}
In either case, you just pass pf or f to your refactored function as a parameter. Using lambdas or templates is overkill here.

Related

Passing values from a function to another function

I'm new in C++ programming world and I have not understood yet if it's possible (and how) to use an output from a function as input to another function.
#include <iostream>
using namespace std;
int func(int l, int m) {
int x = l * m;
return x;
}
int code(x?) {
...
}
I would like to use output from func (the value x) as an input for code.
Is it possible? How could I do that?
Thanks for the help
EDIT 1:
Really thanks for the answers. Is it possible also to pass values between functions using pointers?
Functions only "have" values while they are executed.
You can either call the first from the second funtion,
or call the first function, read the return value into a variable and give that value as parameter to the second,
or call the second and give one of its parameters directly as return value from a call to first function.
Here are some examples of the three options, using 1,2,3 as arbitrary integers.
Variant 1:
int func(int l, int m) {
int x = l * m;
return x;
}
int code(void) {
int ValueFromOtherFuntion=func(1,2);
return 3;
}
Variant 2:
int func(int l, int m)
{
int x = l * m;
return x;
}
int code(int XfromOtherFunction)
{
return 3;
}
int parentfunction(void)
{
int ValueFromOtherFuntion=func(1,2);
return code(ValueFromOtherFunction);
}
Variant 3:
int func(int l, int m)
{
int x = l * m;
return x;
}
int code(int XfromOtherFunction)
{
return 3;
}
int parentfunction(void)
{
return code(func(1,2));
}
Yes, what you are looking for is called function composition.
int sum(int a, int b)
{
return a + b;
}
int square(int x)
{
return x*x;
}
int main()
{
std::cout << square(sum(5, 4)); //will calculate (5+4)squared
}
When you write the functions, assume that you already have all the input and proceed just writing what you want that function to do.
As to when you use that function, use "nested functions" or a function inside a function as such:
code(func(l, m));
Function func will execute first and return the value x, thus leaving you with code(x) which will execute after. Its like pealing an onion: one layer to the other.
#include <iostream>
int func(int l, int m) {
int x = l * m;
return x;
}
void code(int x) { // argument type is the same as the return type of func
std::cout << x;
}
int main (){
int result = func(1 ,2); // either store it
code(func(1, 2)); // or pass it directly.
std::cout << result;
return -1;
}
You can call it in your main function (or in any other within scope for what matters):
code(func(l,m))

How a local variable can be taken in this C++ lambda expression?

In the following code:
#include "Simple_window.h"
#include "Graph.h"
int fac(int n) // factorial(n); n!
{
int r = 1;
while(n>1) {
r *= n;
--n;
}
return r;
}
double term(double x,int n) { return pow(x,n)/fac(n); }
double expe(double x,int n) // sum of n terms for x
{
double sum = 0;
for(int i = 0; i<n; ++i) sum += term(x,i);
return sum;
}
int main() {
Simple_window win {Point{100,100},xmax,ymax,""};
for(int n = 0; n<50; ++n) {
ostringstream ss;
ss << "exp approximation; n==" << n;
win.set_label(ss.str());
// get next approximation:
Function e {[n](double x) { return expe(x,n); },
-10,10,Point{300,300},200,30,30; // ***this line doesn't compile***
win.attach(e);
win.wait_for_button();
win.detach(e);
}
}
From the book "Principles and Practice using C++" by Stroustrup, the local variable n isn't taken when I try to compile it, and gives the error message:
No instance of the constructor Graph_lib::Function::Function coincides with the argument list
What is the problem?
By the way, the support code used for the books is https://web.archive.org/web/20191217104940/http://www.stroustrup.com/Programming/PPP2code
Your post is not close to a Minimal Reproducible Example
Here is an example for Minimal Reproducible Example.
In Graph.h Function takes a variable of Fct.
Where Fct is typedef double Fct(double);.
According to this post, lambda expression doesn't translate to function automatically, unless it doesn't create closure object by capturing nothing.
Check this example
typedef double Fct ( double );
typedef double bct ( double, int );
struct Foo{
Foo( Fct f ){};
};
struct bar{
bar( bct f){};
};
int main(){
int n(1);
Foo f{ [](double x){ return x; } };
//Foo f{ [n](double x){ return x*n; } }; // <=== this won't compile
bar b{[](double x, int n){return x*n;}};
}
To pass the n into function f without closure, you may
Change signature from typedef double Fct ( double ); to typedef double Fct ( double, int ); Like my example of bar
Write a function with a constant n.
(Strongly not suggested, unless you never maintain the code ) Global variable to make it possible to change n outside the function.

Pass a function of object of any type to another object in C++

I'm creating a node system (similar to eg. UE4 or Blender's Cycles) in which i can create nodes of different types and use them later. At the moment I have 2 classes of nodes with output functions like these:
class InputInt
{
public:
int output()
{
int x;
std::cin>>x;
return x;
}
};
class RandomInt
{
public:
int rand10()
{
int x;
x = rand()%10;
return x;
}
int rand100()
{
int x;
x = rand()%100;
return x;
}
};
I don't pass anything to these nodes. Now I want to create a node which takes and output function from and object of one of above classes. Here is how I implemented it to use InputInt node only:
class MultiplyBy2
{
typedef int (InputInt::*func)();
func input_func;
InputInt *obj;
public:
MultiplyBy2(InputInt *object, func i): obj(object), input_func(i) {}
int output()
{
return (obj->*input_func)()*2;
}
};
Having this I can create and use object of MultiplyBy2 in main() and it works perfectly.
int main()
{
InputInt input;
MultiplyBy2 multi(&input, input.output);
std::cout<<multi.output()<<std::endl;
}
It doesn't obviously work for object of RandomInt as I have to pass *InputInt object to MultiplyBy2 object. Is there a way to make MultiplyBy2 take any kind of an object with its output function eg. like this?
int main()
{
RandomInt random;
MultiplyBy2 multi2(&random, random.rand10);
std::cout<<multi2.output()<<std::endl;
}
An alternative approach, using a common base class with virtual methods:
#include <iostream>
struct IntOp {
virtual int get() = 0;
};
struct ConstInt: IntOp {
int n;
explicit ConstInt(int n): n(n) { }
virtual int get() override { return n; }
};
struct MultiplyIntInt: IntOp {
IntOp *pArg1, *pArg2;
MultiplyIntInt(IntOp *pArg1, IntOp *pArg2): pArg1(pArg1), pArg2(pArg2) { }
virtual int get() override { return pArg1->get() * pArg2->get(); }
};
int main()
{
ConstInt i3(3), i4(4);
MultiplyIntInt i3muli4(&i3, &i4);
std::cout << i3.get() << " * " << i4.get() << " = " << i3muli4.get() << '\n';
return 0;
}
Output:
3 * 4 = 12
Live Demo on coliru
As I mentioned std::function in post-answer conversation with OP, I fiddled a bit with this idea and got this:
#include <iostream>
#include <functional>
struct MultiplyIntInt {
std::function<int()> op1, op2;
MultiplyIntInt(std::function<int()> op1, std::function<int()> op2): op1(op1), op2(op2) { }
int get() { return op1() * op2(); }
};
int main()
{
auto const3 = []() -> int { return 3; };
auto const4 = []() -> int { return 4; };
auto rand100 = []() -> int { return rand() % 100; };
MultiplyIntInt i3muli4(const3, const4);
MultiplyIntInt i3muli4mulRnd(
[&]() -> int { return i3muli4.get(); }, rand100);
for (int i = 1; i <= 10; ++i) {
std::cout << i << ".: 3 * 4 * rand() = "
<< i3muli4mulRnd.get() << '\n';
}
return 0;
}
Output:
1.: 3 * 4 * rand() = 996
2.: 3 * 4 * rand() = 1032
3.: 3 * 4 * rand() = 924
4.: 3 * 4 * rand() = 180
5.: 3 * 4 * rand() = 1116
6.: 3 * 4 * rand() = 420
7.: 3 * 4 * rand() = 1032
8.: 3 * 4 * rand() = 1104
9.: 3 * 4 * rand() = 588
10.: 3 * 4 * rand() = 252
Live Demo on coliru
With std::function<>, class methods, free-standing functions, and even lambdas can be used in combination. So, there is no base class anymore needed for nodes. Actually, even nodes are not anymore needed (explicitly) (if a free-standing function or lambda is not counted as "node").
I must admit that graphical dataflow programming was subject of my final work in University (though this is a long time ago). I remembered that I distinguished
demand-driven execution vs.
data-driven execution.
Both examples above are demand-driven execution. (The result is requested and "pulls" the arguments.)
So, my last sample is dedicated to show a simplified data-driven execution (in principle):
#include <iostream>
#include <vector>
#include <functional>
struct ConstInt {
int n;
std::vector<std::function<void(int)>> out;
ConstInt(int n): n(n) { eval(); }
void link(std::function<void(int)> in)
{
out.push_back(in); eval();
}
void eval()
{
for (std::function<void(int)> &f : out) f(n);
}
};
struct MultiplyIntInt {
int n1, n2; bool received1, received2;
std::vector<std::function<void(int)>> out;
void set1(int n) { n1 = n; received1 = true; eval(); }
void set2(int n) { n2 = n; received2 = true; eval(); }
void link(std::function<void(int)> in)
{
out.push_back(in); eval();
}
void eval()
{
if (received1 && received2) {
int prod = n1 * n2;
for (std::function<void(int)> &f : out) f(prod);
}
}
};
struct Print {
const char *text;
explicit Print(const char *text): text(text) { }
void set(int n)
{
std::cout << text << n << '\n';
}
};
int main()
{
// setup data flow
Print print("Result: ");
MultiplyIntInt mul;
ConstInt const3(3), const4(4);
// link nodes
const3.link([&mul](int n) { mul.set1(n); });
const4.link([&mul](int n) { mul.set2(n); });
mul.link([&print](int n) { print.set(n); });
// done
return 0;
}
With the dataflow graph image (provided by koman900 – the OP) in mind, the out vectors represent outputs of nodes, where the methods set()/set1()/set2() represent inputs.
Output:
Result: 12
Live Demo on coliru
After connection of graph, the source nodes (const3 and const4) may push new results to their output which may or may not cause following operations to recompute.
For a graphical presentation, the operator classes should provide additionally some kind of infrastructure (e.g. to retrieve a name/type and the available inputs and outputs, and, may be, signals for notification about state changes).
Surely, it is possible to combine both approaches (data-driven and demand-driven execution). (A node in the middle may change its state and requests new input to push new output afterwards.)
You can use templates.
template <typename UnderlyingClass>
class MultiplyBy2
{
typedef int (UnderlyingClass::*func)();
func input_func;
UnderlyingClass *obj;
public:
MultiplyBy2(UnderlyingClass *object, func i) : obj(object), input_func(i) {}
int output()
{
return (obj->*input_func)() * 2;
}
};
int main()
{
// test
InputInt ii;
MultiplyBy2<InputInt> mii{ &ii, &InputInt::output };
RandomInt ri;
MultiplyBy2<RandomInt> mri{ &ri, &RandomInt::rand10 };
}
This is a bit convoluted. However I think you should be making an interface or class that returns a value and the objects should inherit from this. Then the operator class can take any class that inherits from the base/interface. Eg Make an BaseInt class that stores an int and has the output method/ RandomInt and InputInt should inherit from BaseInt

mem_fn to mem_fn of member

This is a follow-up question to
mem_fn to function of member object
This is the current code.
#include <vector>
#include <algorithm>
#include <functional>
struct Int
{
Int(int _x = 0) : x(_x) {}
int GetInt() const { return x; }
int x;
};
struct IntWrapper
{
IntWrapper(int _x = 0) : test(_x) {}
int GetWrappedInt() const { return test.GetInt(); }
Int test;
};
template<class ContainerT, class Mem> constexpr auto maxElem(const ContainerT& _container, Mem _Pm)
{
auto memFn = std::mem_fn(_Pm);
return memFn(std::max_element(_container.cbegin(), _container.cend(), [&](auto _rhs, auto _lhs) { return memFn(_rhs) < memFn(_lhs); }));
}
int main()
{
{
std::vector<Int> vec;
for (int i = 0; i < 10; ++i)
{
vec.push_back(i * 11 % 7); // some random values
}
int m = maxElem(vec, &Int::GetInt);
int n = maxElem(vec, &Int::x);
}
{
std::vector<IntWrapper> vec;
for (int i = 0; i < 10; ++i)
{
vec.push_back(i * 7 % 11); // some random values
}
int m = maxElem(vec, &IntWrapper::GetWrappedInt);
//int o = maxElem(vec, ???) // what if GetWrappedInt didn't exist?
}
return 0;
}
The original question was about retrieving the x value of the Int struct through anIntWrapper object. I used mem_fn for this because it doesn't seem to distinguish between a function returning an int and an int member variable (Seen in these lines:
int m = maxElem(vec, &Int::GetInt);
int n = maxElem(vec, &Int::x);
The solution for IntWrapper objects was to add .test
auto y = std::mem_fn(&Int::GetInt);
auto b = y(wrapper.test);
to the call. However, in the maxElem function, I cannot do this.
I'm wondering if there is a way to formulate the call in such a way that the mem_fn goes from the IntWrapper object directly to the int x variable (Without the helper function and assuming that all members are public).
//int o = maxElem(vec, ???) // what if GetWrappedInt didn't exist?
The original approach was auto y = std::mem_fn(&IntWrapper::test.GetInt); // ERROR, which of course does not compile, but shows the idea.
Thanks in advance!
You cannot use std::mem_fn with something different than a pointer to member (such as a pointer to member of member). So, you must use that. In your particular case, you can achieve that with
std::vector<IntWrapper> vec;
for (int i = 0; i < 10; ++i)
{
vec.push_back(i * 11 % 7); // some random values
}
auto m = maxElem(vec, &IntWrapper::GetWrappedInt);
However, I strongly advise you to use lambda expressions whenever possible. std::mem_fn should be considered as if deprecated, since, AFAIK, it serves no purpose that cannot be achieved at least as well by other means, i.e. a lambda.

Call map key to invoke function requiring a parameter - how to get working

Here is my code.
#include <map>
#include <string>
#include <algorithm>
class maptest {
public:
int doubler(int val) { return val * 2; }
int halver(int val) { return val / 2; }
int negativer(int val) { return val > 0 ? -val : val; }
};
int main() {
const char* const ID[] = {"doubler", "halver", "negativer" };
int ID_SIZE = sizeof(ID) / sizeof(*ID);
//signature of maths functions
typedef int (maptest::*mathfunc)(int);
mathfunc mfuncs[] = { &maptest::doubler, &maptest::halver, &maptest::negativer};
std::map<std::string, mathfunc> mathmap;
for(int i = 0; i < ID_SIZE; ++i) {
mathmap.insert(std::make_pair(ID[i], mfuncs[i]));
}
//C2064: term does not evaluate to a function taking 1 argument
int result = *mathmap["doubler"](3);
return 0;
}
I think this would work if there was no parameter to be passed to the functions. But how do I pass a parameter in this way?
Your mathfuncs are member functions, so you need an object on which to invoke them:
maptest mt;
int result = (mt.*(mathmap["doubler"]))(3);
Alternatively, you could make your member functions static:
class maptest {
public:
static int doubler(int val) { return val * 2; }
static int halver(int val) { return val / 2; }
static int negativer(int val) { return val > 0 ? -val : val; }
};
And then define mathfunc accordingly:
typedef int (*mathfunc)(int);
And this would allow you to invoke them the way you are invoking them in your original post:
typedef int (*mathfunc)(int);
Notice, that a way to make this design more flexible is to make use of std::function, which would allow you to pass any type of callable object. For instance:
typedef std::function<int(int)> mathfunc;
mathfunc mfuncs[] = {
&maptest::doubler,
&maptest::halver,
&maptest::negativer,
[] (int i) { return i * 2; } // <== A LAMBDA...
};
You are invoking non static member function.
do the following.
maptest t;
int (maptest::*tptr) (int) = mathmap["doubler"];
int result = (t.*tptr)(2);
Hope this helps.