我试图让函数指针操作变得“更流畅”,但当有两个重载:const 和非常量时,我在将成员函数传递给
std::function
时遇到了问题。根据其他 stackoverflow 帖子,我最终成功了,使用 static_cast
但它几乎是可读的。#include <functional>
struct dummy {
int val = 42;
int get() const { return val; }
int& get() { return val; }
};
int main() {
dummy obj;
// std::function<int& (dummy &)> f = &dummy::get;
// std::function<int (dummy const &)> f = &dummy::get;
std::function<int&(dummy&)> f = static_cast<int& (dummy::*)()>(&dummy::get);
std::function<int(dummy const&)> fc =
static_cast<int (dummy::*)() const>(&dummy::get);
// just to check that it works as expected
f(obj) = 36;
return fc(obj); // ok retrives 36
}
直播
有没有更简单的语法?
您可以使用 lambda 表达式:
std::function<int&(dummy&)> f = [](dummy& d) -> int& { return d.get(); };
std::function<int(dummy const&)> fc = [](const dummy& d) { return d.get(); };
我没能说服 gcc 在没有明确指定
int&
返回类型为ough的情况下接受第一行。
如果您实际上想保留函数指针,我不知道有什么“更简单”的东西。恕我直言,
static_cast
非常清楚发生了什么。可以使用类型别名来使其不那么冗长,但它的可读性也肯定会降低。
重载集的地址无法减少
std::function
,但您可以编写帮助程序来简化“转换”:
template <typename Ret, typename C, typename...Ts>
auto overload(Ret(C::*m)(Ts...)) { return m; }
template <typename Ret, typename C, typename...Ts>
auto const_overload(Ret(C::*m)(Ts...) const) { return m; }
然后
std::function<int& (dummy &)> f = overload(&dummy::get);
std::function<int (dummy const &)> fc = const_overload(&dummy::get);
这些助手无法帮助区分
void C::foo(int)
/void C::foo(float)
,并且需要其他助手。