将成员函数 const 和非常量重载传递给 std::function

问题描述 投票:0回答:2

我试图让函数指针操作变得“更流畅”,但当有两个重载: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
}

直播
有没有更简单的语法?

c++ overloading function-pointers pointer-to-member std-function
2个回答
1
投票

您可以使用 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
非常清楚发生了什么。可以使用类型别名来使其不那么冗长,但它的可读性也肯定会降低。


1
投票

重载集的地址无法减少

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)
,并且需要其他助手。

© www.soinside.com 2019 - 2024. All rights reserved.