as the below code, I don't want so many "if else"
class A
{
public:
void f0()
{
cout << "f0" << endl;
}
void f1()
{
cout << "f1" << endl;
}
void f2()
{
cout << "f2" << endl;
}
//..... more functions fn()...
};
class B
{
public:
void f(int n)
{
//vector< function<void()> > f_v {obj_a.f0, obj_a.f1, obj_a.f2}; //this usage is not correct
if (n == 0)
obj_a.f0();
else if (n == 1)
obj_a.f1();
else if (n == 2)
obj_a.f2();
//.....more else if here
}
private:
A obj_a;
};
I want to create a vector
and use std::function
to avoid using so many if-else
, like vector< function<void()> > f_v {obj_a.f0, obj_a.f1, obj_a.f2};
but it doesn't work, maybe the usage of std::function is not very correct. How should I do? Or is there any other good way to solve the problem of if else
, I think use so many switch-case
is also not very elegant :)
update:
Some answers have already solve my problem about the usage of std::function
in my earlier code;
More generally, considering the below code, if the member functons A::f1(), A::f2().... have different return types, but still have some connection that they derived from a same base class , what's the good way to implement the logic of if else
in B::f()
?
class Base
{
public:
virtual ~Base()=default;
};
class D1 : public Base
{
public:
};
class D2 : public Base
{
public:
};
class D3 : public Base
{
public:
};
// ....maybe more class derived form Base
class A
{
public:
D1* f0()
{
cout << "f0" << endl;
return &d1;
}
D2* f1()
{
cout << "f1" << endl;
return &d2;
}
D3* f2()
{
cout << "f2" << endl;
return &d3;
}
//more fn()....
private:
D1 d1;
D2 d2;
D3 d3;
//.....
};
class B
{
public:
void f(int n)
{
if (n == 0)
obj_a.f0();
else if (n == 1)
obj_a.f1();
else if (n == 2)
obj_a.f2();
//.....more else if here
}
private:
A obj_a;
};
CodePudding user response:
You can use std::function
with a lambda wrapper,
vector<function<void()>> f_v {[this]() { obj_a.f0(); },
[this]() { obj_a.f1(); },
[this]() { obj_a.f2(); }};
f_v[n]();
or use pointer-to-members directly,
vector<void (A::*)()> f_v { &A::f0, &A::f1, &A::f2 };
(obj_a.*f_v[n])();
CodePudding user response:
If you are aiming at speed and you know the number of methods, avoid using std::vector for the extra indirection. Use std::array as it will hit cache with the current object.
For this simple case, you don't necessarily need to use std::function, which is a very heavy object to call. You can use pointers to members like this:
#include <iostream>
#include <array>
using namespace std;
class A
{
public:
void f0()
{
cout << "f0" << endl;
}
void f1()
{
cout << "f1" << endl;
}
void f2()
{
cout << "f2" << endl;
}
//.....
};
class B
{
public:
B() {
fn[0] = &A::f0;
fn[1] = &A::f1;
fn[2] = &A::f2;
}
void f(int n)
{
((obj_a).*(fn[n]))();
}
private:
using Fn = void (A::*)();
std::array<Fn,3> fn;
A obj_a;
};
Code: https://godbolt.org/z/z4KqKvn99
CodePudding user response:
Your approach seems correct. You just need to std::bind those member functions like
class B{
std::vector <std::function <void()>> m_vec_functs;
...
B(const A& a)
{
m_vec_functs.push_back(std::bind(&A::f0, a));
m_vec_functs.push_back(std::bind(&A::f1, a));
}
void f(unsigned int n)
{
m_vec_functs[n];
}
...
};
Then you can access each individual function by its index, knowing their order.