Is it possible to enumerate functions in C++? - c++

Suppose I have some functions which have the same parameters and datatype, and I want to push them into a std::vector and enumerate them.
Is it possible to do this?
Pseudocode:
typedef int func(int, int);
int add(int a, int b)
{
return a + b;
}
int minus(int a, int b)
{
return a - b;
}
vector<func> operations = {add, minus};
for (auto operation : operations)
{
// do something
}

What you are missing in your code is a * in std::vector<func> because you want to store pointers to the function:
#include <vector>
#include <functional>
#include <iostream>
typedef int func(int, int);
int add(int a, int b)
{
return a + b;
}
int minus(int a, int b)
{
return a - b;
}
int main() {
std::vector<func*> operations = {add, minus};
for (auto operation : operations)
{
}
}
You could also use std::function for that purpose:
#include <vector>
#include <functional>
int add(int a, int b)
{
return a + b;
}
int minus(int a, int b)
{
return a - b;
}
int main() {
std::vector<std::function<int(int,int)>> operations = {add, minus};
for (auto operation : operations)
{
// do something
}
}
Related question:
How can I store function pointer in vector?

Related

Creating a pointer to a class in a function belonging to a different class

I'm trying to populate a vector of type pointer to class B, which I'll be using later.
When I try to read the vector's element, the value I'm getting is different from what I've given.
Can someone please help me here, what mistake I'm making and how to correct it?
Thanks
#include <iostream>
#include <vector>
class B {
public:
int b;
B (int n) {
b = n;
}
};
std::vector<B*> v;
class A {
public:
int a;
void func(int n);
};
void A::func(int n) {
B obj_b(n);
B* ptr = &obj_b;
v.push_back(ptr);
}
int main() {
A obj_a;
obj_a.a = 5;
obj_a.func(4);
std::cout<<obj_a.a<<std::endl;
for (auto it:v) {
std::cout<<it->b<<std::endl;
}
}
The output I'm getting is:
5,
32765
Whereas the expected output is:
5,
4
Using value instead of pointer, as per the comments above:
#include <iostream>
#include <vector>
class B {
public:
int b;
B (int n) {
b = n;
}
};
std::vector<B> v;
class A {
public:
int a;
void func(int n);
};
void A::func(int n) {
v.emplace_back(n);
}
int main() {
A obj_a;
obj_a.a = 5;
obj_a.func(4);
std::cout<<obj_a.a<<std::endl;
for (auto& e:v) {
std::cout<<e.b<<std::endl;
}
}
You can use heap allocations and take advantage of std::unique_ptr<T>. Here is the fix:
#include <iostream>
#include <vector>
#include <memory>
class B
{
public:
B ( const int n )
{
b = n;
}
int b;
};
std::vector< std::unique_ptr<B> > v; // use a vector of B pointers
// ( std::unique_ptr<B> )
class A
{
public:
void func( const int n );
int a;
};
void A::func( const int n )
{
v.push_back( std::make_unique<B>( n ) ); // returns a pointer object of type
} // std::unique_ptr<B>
int main ()
{
A obj_a;
obj_a.a = 5;
obj_a.func( 4 );
std::cout << obj_a.a << std::endl;
for ( const auto& ptrB : v )
{
std::cout << ptrB->b << std::endl; // use -> operator to have access to
} // ptrB's members
return 0;
}
Hopefully, this helps.

How to remove an element from a vector using remove_if

I have the below code: I face compilation error in remove function. I want to remove the elements from the vector whose elements have an x match the value of input x.
class A
{
int x,y;
public:
init(int a, int b)
{
x = a; y= b;
}
int getX(){return x;}
}
class B
{
public:
void add (int a, int b)
{
A a1;
a1.init(a,b);
MyVector.push_back(a1);
}
void remove(int x)
{
MyVector.erase(remove_if(MyVector.begin(), MyVector.end(),
[&vec](int x){return (vec.getX() == x);}), MyVector.end());
}
vector<A> MyVector;
}
You must give a return type to init(int a, int b) and you've missed two ;s after the classes definitions and used std::remove_if() incorrectly. here is its documentation
#include <vector>
#include <algorithm>
class A
{
int x,y;
public:
void init(int a, int b)
{
x = a; y= b;
}
int getX(){return x;}
};
class B
{
public:
void add (int a, int b)
{
A a1;
a1.init(a,b);
MyVector.push_back(a1);
}
void remove(int x)
{
MyVector.erase(std::remove_if(MyVector.begin(), MyVector.end(),
[&x](auto & el){return (el.getX() == x);}), MyVector.end());
}
std::vector<A> MyVector;
};
Note that auto & el == A & el. std::remove_if iterates over the vector and passes its elements to the lambda, hence the lambda argument type should be as the vector's one.

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();
}

How to best pass methods into methods of the same class

I have this C++ class that one big complicated method compute that I would like to feed with a "compute kernel", a method of the same class. I figure I would do something along the lines of
class test {
int classVar_ = 42;
int compute_add(int a, int b)
{
compute(int a, int b, this->add_())
}
int compute_mult(int a, int b)
{
compute(int a, int b, this->mult_())
}
int compute_(int a, int b, "pass in add or multiply as f()")
{
int c=0;
// Some complex loops {
c += f(a,b)
// }
return c;
}
int add_(int a, int b){a+b+classVar_;}
int multiply_(int a, int b){a*b+classVar_;}
...
}
but I'm not sure how I would pass in add or multiply.
An alternative to this approach would be to pass in an ENUM of some sort to specify add() or multiply(), but I wanted to avoid a switch or if inside the loops.
What's best practice here?
As you suspected, passing a member function pointer is acceptable practice.
If you need to know the syntax, it is:
int compute_(int a, int b, int (test::*f)(int,int))
{
int c=0;
// Some complex loops {
c += (this->*f)(a,b)
// }
return c;
}
Representing member functions using integers, and switching, introduces programmer overhead to keep things up to date when the list of available operations changes. So you don't want that unless there's some important reason in a particular case.
One alternative is to make compute even more general -- instead of taking a member function, write a function template that takes any callable type:
template <typename BinaryFunction>
int compute_(int a, int b, BinaryFunction f) {
// body as before but `f(a,b)` instead of `(this->*f)(a,b)`
}
This more general template is great if someone wants to use it with some operator of their own invention, that isn't a member function of test. It's more difficult to use in the case of the member function, though, because someone needs to capture this. There are a few ways to do that -- a C++11 lambda, boost::bind, or writing out a functor longhand. For example:
template <typename BinaryFunction>
int compute_(int a, int b, BinaryFunction f) {
// body as before with `f(a,b)`
}
int compute_(int a, int b, int (test::*f)(int,int))
{
return compute_(a, b, bind_this(f, this));
}
Defining bind_this is a bit of a pain: it's like std::bind1st except that we'd like to work with a 3-arg functor whereas bind1st only takes a binary functor. boost::bind, and std::bind in C++11, are more flexible, and will handle the extra arguments. The following will do for this case, but doesn't work in general to bind 2-arg member functions:
struct bind_this {
int (test::*f)(int,int);
test *t;
int operator(int a, int b) const {
return (t->*f)(a,b);
}
bind_this(int (test::*f)(int,int), test *t) : f(f), t(t) {}
};
In C++11 you can just use a lambda:
int compute_(int a, int b, int (test::*f)(int,int))
{
return compute_(a, b, [=](int c, int d){ return (this->*f)(c,d) });
}
Use pointers to functions.
int compute(int a, int b, int (test::*f) (int, int) )
{
int c=0;
// Some complex loops {
c += (this->*f)(a,b)
// }
return c;
}
You have two alternatives :
using pointer to member function
using lambda functions
Example using pointer to member function :
#include <iostream>
class D
{
public:
D(int v ) : classVar_(v){}
int add_(int a, int b){return (a+b+classVar_);}
int multiply_(int a, int b){return (a*b+classVar_);}
private:
int classVar_;
};
class test {
public:
int compute_(int a, int b, D &d, int (D::*f)(int a, int b))
{
int c=0;
// Some complex loops {
c += (d.*f)(a,b);
// }
return c;
}
};
int main()
{
test test;
D d(1);
std::cout<<"add : " << test.compute_( 5, 4, d, &D::add_ ) << std::endl;
std::cout<<"add : " << test.compute_( 5, 4, d, &D::multiply_ ) << std::endl;
}
Example using lambda :
#include <iostream>
#include <functional>
class D
{
public:
D(int v ) : classVar_(v){}
int add_(int a, int b){return (a+b+classVar_);}
int multiply_(int a, int b){return (a*b+classVar_);}
private:
int classVar_;
};
class test {
public:
int compute_(int a, int b, std::function< int(int,int) > f)
{
int c=0;
// Some complex loops {
c += f(a,b);
// }
return c;
}
};
int main()
{
test test;
D d(1);
std::cout<<"add : " << test.compute_( 5, 4, [&d](int a, int b){ return d.add_(a,b); } ) << std::endl;
std::cout<<"add : " << test.compute_( 5, 4, [&d](int a, int b){ return d.multiply_(a,b); } ) << std::endl;
}

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 ()