C++ Reference to member function work around (computation speed) - c++

It is well known that you cannot create a reference to a member function in C++ [source].
For those that don't know. The issue come when you want to do something similar to
class A
{
public:
void Add(int a, int b)
{
std::cout << "Sum is " << a + b << std::endl;
}
void CallAdd(int a, int b, void (*func)(int, int))
{
func(a, b);
}
};
and then call Add through CallAdd:
A a;
a.Add(3, 7); // This works fine
a.CallAdd(3, 7, &a.CallAdd); //This does not compile
The error is
error: cannot create a non-constant pointer to member function
a.CallAdd(3, 7, &a.CallAdd);
Which would not occur if it wiere outside a class.
There is a work around using std::function/lambda. Like this:
class A
{
public:
function<void(int, int)> AddFunc = [](int a, int b)
{
std::cout << "Sum is " << a + b << std::endl;
};
void CallAdd(int a, int b, std::function<void(int, int)> &func)
{
func(a, b);
};
};
int main()
{
A a;
a.CallAdd(3, 7, a.AddFunc);
}
This works fine but the problem is that computation time increases a lot (obviously this is just a minimal reproducible example) compared to simply calling the function.
Is there a way to increase computation speed or is this the best one can do?
For context, I have an algorithm to integrate functions, and I want to change integrands at will so the integrand must be a function parameter.

Pass the function object (or lambda) to a templated member function as follows:
#include <concepts>
#include <iostream>
inline auto myAddFunc = [](int a, int b) {
std::cout << "Sum is " << a + b << std::endl;
};
class A
{
public:
template <std::regular_invocable<int,int> Func>
void CallFunc(int a, int b, Func func)
{
func(a, b);
};
};
int main()
{
A a;
auto mySubFunc = [](int a, int b) {
std::cout << "Difference is " << a - b << std::endl;
};
a.CallFunc(3, 7, myAddFunc);
a.CallFunc(7, 3, mySubFunc);
}

Related

How can I pass a class method as a parameter to another function and later call it, preferably making the variable class method signature explicit?

If I have a class that needs to call a parent class method with a class method as parameter I can do it with std::function + std::bind as shown below:
class A {
void complexMethod(std::function<void()> variableMethod) {
// other stuff ...
variableMethod();
// some other stuff..
}
}
class B : public A {
void myWay() {
// this and that
}
void otherWay() {
// other and different
}
void doingSomething() {
// Preparing to do something complex.
complexMethod(std::bind(&B::myWay, this));
}
void doingAnotherThing() {
// Different preparation to do some other complex thing.
complexMethod(std::bind(&B::otherWay, this));
}
}
How would I need to change the above code to implement the same thing using templates instead of std::function + std::bind?
And how about lambdas instead of std::function + std::bind? I still want to call B:myWay() and B::otherWay() but using lambdas. I don't want to substitute B:myWay() and B::otherWay() with lambdas.
Is there any implementation technique (one of the above or some other) were I would be able to make variableMethod return type and parameters explicit? How would I do it? Let's say the signature of variableMethod is:
bool variableMethod(int a, double b);
Which technique is recommended? Why (speed, flexibility, readility...)?
Template + lambda solution:
struct A
{
template <typename F>
void runA(F func)
{
cout << 1 << endl;
func();
cout << 3 << endl;
}
};
struct B : A
{
int number = 2;
void runnable() { cout << number << endl; }
void runB()
{
cout << 0 << endl;
runA([this]() { runnable(); });
cout << 4 << endl;
}
};
int main()
{
B variable;
variable.runB();
}
In order to take a function as template parameter, just take in a template type of that function like above. lambdas can be used instead of bind to make things easier (this is passed to lambda captures list).
Explicitly declaring the arguments:
void run_func(std::function<bool(int, double)> func)
{
bool b = func(10, 10.01);
}
std::function allows you to define your arguement and return types like above.
How would I need to change the above code to implement the same thing
using templates instead of std::function + std::bind?
And how about lambdas instead of std::function + std::bind? I
still want to call B:myWay() and B::otherWay() but using lambdas.
I don't want to substitute B:myWay() and B::otherWay() with
lambdas.
You can use a lambda, yes.
Something like [this]() { return myWay(); } that:
captures this, and
calls a method of the current object.
[Demo]
#include <iostream> // cout
class A {
protected:
template <typename F>
void complexMethod(F&& f) { f(); }
};
class B : public A {
void myWay() { std::cout << "myWay\n"; }
void otherWay() { std::cout << "otherWay\n"; }
public:
void doingSomething() {
complexMethod([this]() { return myWay(); });
}
void doingAnotherThing() {
complexMethod([this]() { return otherWay(); });
}
};
int main() {
B b{};
b.doingSomething();
b.doingAnotherThing();
}
// Outputs:
//
// myWay
// otherWay
Is there any implementation technique (one of the above or some other)
were I would be able to make variableMethod return type and
parameters explicit? How would I do it?
You could use const std::function<bool(int,double)>& f as the parameter receiving a function for complexMethod. And still pass a lambda. Notice though lambdas are now receiving (int i, double d) (it could be (auto i, auto d) as well).
[Demo]
#include <functional> // function
#include <ios> // boolalpha
#include <iostream> // cout
class A {
protected:
bool complexMethod(const std::function<bool(int,double)>& f, int i, double d)
{ return f(i, d); }
};
class B : public A {
bool myWay(int a, double b) { return a < static_cast<int>(b); }
bool otherWay(int a, double b) { return a*a < static_cast<int>(b); }
public:
bool doingSomething(int a, double b) {
return complexMethod([this](int i, double d) {
return myWay(i, d); }, a, b);
}
bool doingAnotherThing(int a, double b) {
return complexMethod([this](auto i, auto d) {
return otherWay(i, d); }, a, b);
}
};
int main() {
B b{};
std::cout << std::boolalpha << b.doingSomething(3, 5.5) << "\n";
std::cout << std::boolalpha << b.doingAnotherThing(3, 5.5) << "\n";
}
// Outputs:
//
// true
// false
Notice also the same could be accomplished with templates, although you wouldn't be making the signature explicit.
[Demo]
#include <functional> // function
#include <ios> // boolalpha
#include <iostream> // cout
class A {
protected:
template <typename F, typename... Args>
auto complexMethod(F&& f, Args&&... args) -> decltype(f(args...))
{ return f(args...); }
};
class B : public A {
bool myWay(int a, double b) { return a < static_cast<int>(b); }
bool otherWay(int a, double b) { return a*a < static_cast<int>(b); }
public:
bool doingSomething(int a, double b) {
return complexMethod([this](auto i, auto d) {
return myWay(i, d); }, a, b);
}
bool doingAnotherThing(int a, double b) {
return complexMethod([this](auto i, auto d) {
return otherWay(i, d); }, a, b);
}
};
int main() {
B b{};
std::cout << std::boolalpha << b.doingSomething(3, 5.5) << "\n";
std::cout << std::boolalpha << b.doingAnotherThing(3, 5.5) << "\n";
}
// Outputs:
//
// true
// false
Which technique is recommended? Why (speed, flexibility,
readility...)?
Item 34 of Scott Meyer's Effective Modern C++ book is titled Prefer lambdas to std::bind. It ends with a summary saying: Lambdas are more readable, more expressive, and may be more efficient than using std::bind. However, it also mentions a case when std::bind may be useful over lambdas.

How to properly pass member function as a parameter

How do I properly pass member function as a parameter?
MyCode:
#include <iostream>
using namespace std;
class Test
{
public:
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
typedef int (*funcPtr)(int a, int b);
int myFunc(funcPtr func, int a, int b)
{
return func(a, b);
}
void setup()
{
cout << myFunc(&Test::add, 5, 3) << endl;
cout << myFunc(&Test::sub, 5, 3) << endl;
}
};
int main()
{
Test test;
test.setup();
}
Result:
Error: Cannot initialize a parameter of type 'Test::funcPtr' (aka 'int
()(int, int)') with an rvalue of type 'int (Test::)(int, int)'
Expected Result:
8
2
Your methods should be "regular" functions. add static to them to allow to use them with function pointers:
class Test
{
public:
static int add(int a, int b)
{
return a + b;
}
static int sub(int a, int b)
{
return a - b;
}
// ...
};
If you really pointer on method, you should replace int (*funcPtr)(int a, int b) by int (Test::*funcPtr)(int a, int b) and use something like that instead:
class Test
{
public:
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
typedef int (Test::*funcPtr)(int a, int b);
int myFunc(funcPtr func, int a, int b)
{
return (this->*func)(a, b);
}
void setup()
{
cout << myFunc(&Test::add, 5, 3) << endl;
cout << myFunc(&Test::sub, 5, 3) << endl;
}
};
You should read about std:: function and std::bind. The first thing will allow you to store a function pointer with multiple form (Functor, lamda, binded), and the second will allow you to bind parameters to your function call (In your case, you want to bind the instance of the class that is needed to call your function).
std:: function<int(int, int)> func = std::bind(&Class::Method, instancePtr, std::placeholders::_1, std:: placeholders::_2);
int result = func(a, b);
However, in your context, your methods should be marked as static (They are not using any non-static member of your class), but the example and the explanation I provided answer to your base question
Firstly, based on your question the best solution here will be without using the pointer instead declare your methods as static and call them directly as given below.
That solution will generate the right results without using the complexity of pointers.
Simple is better if you do not need to use pointers it is better to not use them. code will be more readable as well.
Following code works i tested it:
#include <iostream>
using namespace std;
class Test
{
public:
static int add(int a, int b)
{
return a + b;
}
static int sub(int a, int b)
{
return a - b;
}
void setup()
{
cout << add( 5, 3) << endl;
cout << sub(5, 3) << endl;
}
};
int main()
{
Test test;
test.setup();
}

Alternative to std::bind when passing member function

I have some functions I'd like to benchmark. I would like be able to pass them into the benchmarking function. Previously I have passed a function pointer and reference to the object to the testing function like so
template<typename T>
void (T::*test_fn)(int, int), T& class_obj, )
At the moment I have this
#include <iostream>
#include <functional>
using namespace std::placeholders;
class aClass
{
public:
void test(int a, int b)
{
std::cout << "aClass fn : " << a + b << "\n";
}
};
class bClass
{
public:
void test(int a, int b)
{
std::cout << "bClass fn : " << a * b << "\n";
}
};
// Here I want to perform some tests on the member function
// passed in
class testing
{
public:
template<typename T>
void test_me(T&& fn, int one, int two)
{
fn(one, two);
}
};
int main()
{
aClass a;
bClass b;
auto fn_test1 = std::bind(&aClass::test, a, _1, _2);
auto fn_test2 = std::bind(&bClass::test, b, _1, _2);
testing test;
test.test_me(fn_test1, 1, 2);
test.test_me(fn_test2, 1, 2);
}
Is there a way I can do this using a lambda instead?
I know I can do this using std::bind but can I do this using a lambda and not have to do it each time for each member function I want to test (as below)?
The test_me function can take any callable object. Including lambdas. No modifications needed.
Something like
test.test_me([a](int one, int two) { a.test(one, two); }, 1, 2);

Is it possible to pass a struct's member variable as parameter

I am trying to associate a struct's member variable with a class. So that when I create a new class, I can specify that it is associated with this member variable in a struct. For example:
struct A {
int a;
int b;
};
static A a[2];
a[0].a = 1;
a[0].b = 2;
a[1].a = 3;
a[1].b = 4;
class foo {
public:
foo(int index, ???) {
c = a[index].???; //Is it possible to define the 2nd parameter as a getter of struct A's member? So this line could resolve to either a[index].a or a[index].b?
}
private:
int c;
};
So that:
new foo(0, ???) would set c to 1 given ??? refer to A::a
new foo(0, ???) would set c to 2 given ??? refer to A::b
new foo(1, ???) would set c to 3 given ??? refer to A::a
new foo(1, ???) would set c to 4 given ??? refer to A::b
Yes, it is possible, you need to pass a data member pointer:
#include <iostream>
struct A
{
int a;
int b;
};
static A a[2]
{
1, 2
, 3, 4
};
class foo
{
public: int c;
public:
foo(int const index, int A::* const p_field)
{
c = a[index].*p_field;
}
};
int main()
{
foo const f1(0, &A::a);
::std::cout << f1.c << ::std::endl;
foo const f2(0, &A::b);
::std::cout << f2.c << ::std::endl;
foo const f3(1, &A::a);
::std::cout << f3.c << ::std::endl;
foo const f4(1, &A::b);
::std::cout << f4.c << ::std::endl;
return 0;
}
Check this code at online compiler
You have a couple options. If you just want the integer (like you have in your code you've posted), then just take an integer as a parameter to the constructor and pass it the right number.
class foo {
public:
foo(int val) {
c = val
}
private:
int c;
};
int main() {
foo f(a[0].b);
}
Or you could take a reference to an integer. This way if one changes, the other will as well:
class foo {
public:
foo(int &val) : c(val) { } //need to use an initialization list for this one
private:
int &c;
};
int main() {
foo f(a[0].b);
a[0].b = -1; //f.c will be -1 now as well
}
Using a data member pointer as in VTT's answer is the most direct solution but I often find member pointers and member function pointer syntax a bit cumbersome and I believe it is hard for the compiler to optimize.
For these kind of things I prefer to use a stateless lambda. You can pass a lambda to a function template and then the compiler can easily optimize it away:
#include <iostream>
struct A {
int a;
int b;
};
static A a[2]{{1, 2}, {3, 4}};
class foo {
public:
int c;
public:
template<typename F>
foo(int index, F getter) { c = getter(a[index]); }
};
int main() {
auto agetter = [](const A& a){ return a.a; };
auto bgetter = [](const A& a){ return a.b; };
foo const f1(0, agetter);
std::cout << f1.c << "\n";
foo const f2(0, bgetter);
std::cout << f2.c << "\n";
foo const f3(1, agetter);
std::cout << f3.c << "\n";
foo const f4(1, bgetter);
std::cout << f4.c << "\n";
}

operator as template parameter

Is it possible?
template<operator Op> int Calc(int a, b)
{ return a Op b; }
int main()
{ cout << Calc<+>(5,3); }
If not, is way to achieve this without ifs and switches?
You could use functors for this:
template<typename Op> int Calc(int a, int b)
{
Op o;
return o(a, b);
}
Calc<std::plus<int>>(5, 3);
No - templates are about types or primitive values.
You can nontheless pass so called function objects that can be called like functions and carry the desired operator functionality (despite having a nice syntax).
The standard library defines several ones, e.g. std::plus for addition ...
#include <functional>
template<typename Op>
int Calc(int a, int b, Op f) {
return f(a, b);
}
int main() {
cout << Calc(5,3, std::plus());
cout << Calc(5,3, std::minus());
}
You can do this using polymorphism:
#include <cstdlib>
#include <iostream>
using namespace std;
class Operator
{
public:
virtual int operator()(int a, int b) const = 0;
};
class Add : public Operator
{
public:
int operator()(int a, int b) const
{
return a+b;
}
};
class Sub : public Operator
{
public:
int operator()(int a, int b) const
{
return a-b;
}
};
class Mul : public Operator
{
public:
int operator()(int a, int b) const
{
return a*b;
}
};
int main()
{
Add adder;
cout << adder(1,2) << endl;
Sub suber;
cout << suber(1,2) << endl;
Mul muler;
cout << muler(1,2) << endl;
return 0;
}
If you refer to global operators, you have already received some answers. In some particular cases, though, it might also be helpful to use overloaded operator functions.
This might be trivial; nevertheless it might be helpful in some cases which is why I post one example:
#include <iostream>
template<typename opType, typename T>
int operation(opType op, T a, T b)
{
return (a.*op)(1) + (b.*op)(1);
}
struct linear
{
int operator()(int n) const {return n;}
int operator[](int n) const {return n * 10;}
};
int main()
{
linear a, b;
std::cout << operation(&linear::operator(), a, b) << std::endl
<< operation(&linear::operator[], a, b);
return 0;
}
output:
2
20
Use
template<typename Op>
int Calc(int a, int b, Op f) {
return f(a, b);
}
int
main() {
cout << Calc(5, 3, std::plus{});
cout << Calc(5, 3, std::minus{});
}
if Dario answer fails with error: cannot deduce template arguments for ‘plus’ from ()