关于std::function用法和if-else问题
About std::function usage and if-else problem
如下代码,我不想要那么多“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;
};
我想创建一个 vector
并使用 std::function
来避免使用这么多 if-else
,比如 vector< function<void()> > f_v {obj_a.f0, obj_a.f1, obj_a.f2};
但是它不起作用,也许使用std::function 不是很正确。我应该怎么做? 或者有什么其他好的方法可以解决if else
的问题,我觉得用这么多switch-case
也不是很优雅:)
更新:
一些答案已经解决了我在早期代码中使用 std::function
的问题;
更一般地,考虑下面的代码,如果成员函数A::f1(), A::f2()....有不同的return类型,但仍然有一些联系他们来自相同的基础 class ,在 B::f()
中实现 if else
逻辑的好方法是什么?
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;
};
您可以将 std::function
与 lambda 包装器一起使用,
vector<function<void()>> f_v {[this]() { obj_a.f0(); },
[this]() { obj_a.f1(); },
[this]() { obj_a.f2(); }};
f_v[n]();
或者直接使用指向成员的指针,
vector<void (A::*)()> f_v { &A::f0, &A::f1, &A::f2 };
(obj_a.*f_v[n])();
如果您的目标是速度并且知道方法的数量,请避免使用 std::vector 进行额外的间接访问。使用 std::array 因为它将使用当前对象命中缓存。
对于这种简单的情况,您不一定需要使用std::function,这是一个非常重的调用对象。您可以像这样使用指向成员的指针:
#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;
};
您的方法似乎是正确的。您只需要 std::bind 那些成员函数,例如
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];
}
...
};
然后您可以通过索引访问每个单独的函数,知道它们的顺序。
如下代码,我不想要那么多“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;
};
我想创建一个 vector
并使用 std::function
来避免使用这么多 if-else
,比如 vector< function<void()> > f_v {obj_a.f0, obj_a.f1, obj_a.f2};
但是它不起作用,也许使用std::function 不是很正确。我应该怎么做? 或者有什么其他好的方法可以解决if else
的问题,我觉得用这么多switch-case
也不是很优雅:)
更新:
一些答案已经解决了我在早期代码中使用 std::function
的问题;
更一般地,考虑下面的代码,如果成员函数A::f1(), A::f2()....有不同的return类型,但仍然有一些联系他们来自相同的基础 class ,在 B::f()
中实现 if else
逻辑的好方法是什么?
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;
};
您可以将 std::function
与 lambda 包装器一起使用,
vector<function<void()>> f_v {[this]() { obj_a.f0(); },
[this]() { obj_a.f1(); },
[this]() { obj_a.f2(); }};
f_v[n]();
或者直接使用指向成员的指针,
vector<void (A::*)()> f_v { &A::f0, &A::f1, &A::f2 };
(obj_a.*f_v[n])();
如果您的目标是速度并且知道方法的数量,请避免使用 std::vector 进行额外的间接访问。使用 std::array 因为它将使用当前对象命中缓存。
对于这种简单的情况,您不一定需要使用std::function,这是一个非常重的调用对象。您可以像这样使用指向成员的指针:
#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;
};
您的方法似乎是正确的。您只需要 std::bind 那些成员函数,例如
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];
}
...
};
然后您可以通过索引访问每个单独的函数,知道它们的顺序。